From 5e9279cbde968b774db0ffd4ab3e81089abca98f Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 12:26:33 +0100 Subject: [PATCH 01/11] wip --- .github/workflows/ci.yml | 42 +- .prettierrc | 5 + integration/test/ParseLocalDatastoreTest.js | 1654 ++++---- integration/test/ParseUserTest.js | 1069 ++--- jasmine.json | 8 +- package-lock.json | 4001 +++++++++++++------ package.json | 6 +- src/ParseUser.js | 302 +- src/__tests__/ParseUser-test.js | 1165 +++--- 9 files changed, 5263 insertions(+), 2989 deletions(-) create mode 100644 .prettierrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4dc83967..0c961835a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,32 +5,30 @@ on: - master pull_request: branches: - - '**' + - "**" jobs: build: runs-on: ubuntu-18.04 timeout-minutes: 30 - env: + env: MONGODB_VERSION: 3.6.9 steps: - - uses: actions/checkout@v2 - - name: Use Node.js - uses: actions/setup-node@v1 - with: - node-version: '10.14' - - name: Cache Node.js modules - uses: actions/cache@v2 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | + - uses: actions/checkout@v2 + - name: Use Node.js + uses: actions/setup-node@v1 + with: + node-version: "10.14" + - name: Cache Node.js modules + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | ${{ runner.os }}-node- - - run: npm ci - - run: npm install -g mongodb-runner - - run: mongodb-runner start - - run: npm run lint - - run: npm test -- --maxWorkers=4 - - run: npm run integration - env: - CI: true - - run: bash <(curl -s https://codecov.io/bash) + - run: npm ci + - run: npm run lint + - run: npm test -- --maxWorkers=4 + - run: npm run integration + env: + CI: true + - run: bash <(curl -s https://codecov.io/bash) 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/test/ParseLocalDatastoreTest.js b/integration/test/ParseLocalDatastoreTest.js index ecfa9572a..52b818e54 100644 --- a/integration/test/ParseLocalDatastoreTest.js +++ b/integration/test/ParseLocalDatastoreTest.js @@ -1,14 +1,14 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); -const TestObject = Parse.Object.extend('TestObject'); -const Item = Parse.Object.extend('Item'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); +const TestObject = Parse.Object.extend("TestObject"); +const Item = Parse.Object.extend("Item"); -global.localStorage = require('./mockLocalStorage'); -const mockRNStorage = require('./mockRNStorage'); -const LocalDatastoreUtils = require('../../lib/node/LocalDatastoreUtils'); +global.localStorage = require("./mockLocalStorage"); +const mockRNStorage = require("./mockRNStorage"); +const LocalDatastoreUtils = require("../../lib/node/LocalDatastoreUtils"); const DEFAULT_PIN = LocalDatastoreUtils.DEFAULT_PIN; const PIN_PREFIX = LocalDatastoreUtils.PIN_PREFIX; @@ -39,10 +39,10 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName('DO_NOT_CLEAR', {}); + await Parse.LocalDatastore.pinWithName("DO_NOT_CLEAR", {}); let storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); @@ -51,8 +51,8 @@ function runTest(controller) { storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 1); - assert.equal(storage['DO_NOT_CLEAR'], '{}'); - await Parse.LocalDatastore.unPinWithName('DO_NOT_CLEAR'); + assert.equal(storage["DO_NOT_CLEAR"], "{}"); + await Parse.LocalDatastore.unPinWithName("DO_NOT_CLEAR"); }); it(`${controller.name} can getAllContents localDatastore`, async () => { @@ -61,17 +61,17 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName('DO_NOT_FETCH', {}); + await Parse.LocalDatastore.pinWithName("DO_NOT_FETCH", {}); const storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); const LDS = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(LDS).length, 5); - assert.equal(LDS['DO_NOT_FETCH'], null); + assert.equal(LDS["DO_NOT_FETCH"], null); }); it(`${controller.name} can pin (unsaved)`, async () => { @@ -81,7 +81,9 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); - assert.deepEqual(localDatastore[LDS_KEY(object)], [LDS_FULL_JSON(object)]); + assert.deepEqual(localDatastore[LDS_KEY(object)], [ + LDS_FULL_JSON(object), + ]); await object.save(); // Check if localDatastore updated localId to objectId localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -92,7 +94,7 @@ function runTest(controller) { it(`${controller.name} can store data to pin (unsaved)`, async () => { const object = new TestObject(); - object.set('foo', 'bar'); + object.set("foo", "bar"); await object.pin(); const query = new Parse.Query(TestObject); @@ -101,19 +103,19 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'bar'); - pinnedObject.set('foo', 'baz'); + assert.equal(pinnedObject.get("foo"), "bar"); + pinnedObject.set("foo", "baz"); await pinnedObject.pin(); results = await query.find(); assert.equal(results.length, 1); pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'baz'); + assert.equal(pinnedObject.get("foo"), "baz"); }); it(`${controller.name} can query unsaved pin and save`, async () => { const object = new TestObject(); - object.set('foo', 'bar'); + object.set("foo", "bar"); await object.pin(); const query = new Parse.Query(TestObject); @@ -123,9 +125,9 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'bar'); + assert.equal(pinnedObject.get("foo"), "bar"); - pinnedObject.set('foo', 'baz'); + pinnedObject.set("foo", "baz"); await pinnedObject.save(); assert(pinnedObject.id); @@ -134,7 +136,7 @@ function runTest(controller) { results = await query.find(); pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'baz'); + assert.equal(pinnedObject.get("foo"), "baz"); assert(pinnedObject.id); assert.equal(pinnedObject._localId, undefined); }); @@ -142,13 +144,13 @@ function runTest(controller) { it(`${controller.name} can pin unsaved pointer`, async () => { const object = new TestObject(); const pointer = new Item(); - object.set('child', pointer); + object.set("child", pointer); await object.pin(); }); it(`${controller.name} can pin user (unsaved)`, async () => { const user = new Parse.User(); - user.set('field', 'test'); + user.set("field", "test"); await user.pin(); const json = user._toFullJSON(); @@ -160,16 +162,16 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); await Parse.User.logOut(); }); it(`${controller.name} can pin user (saved)`, async () => { const user = new Parse.User(); - user.set('field', 'test'); - user.setPassword('asdf'); - user.setUsername('zxcv'); - await user.signUp() + user.set("field", "test"); + user.setPassword("asdf"); + user.setUsername("zxcv"); + await user.signUp(); await user.pin(); const json = user._toFullJSON(); @@ -182,13 +184,13 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); await Parse.User.logOut(); }); it(`${controller.name} can pin (saved)`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); await object.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -197,16 +199,16 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); }); it(`${controller.name} can pin (twice saved)`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); await object.pin(); - object.set('field', 'new info'); + object.set("field", "new info"); await object.save(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -215,12 +217,12 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, 'new info'); + assert.equal(cachedObject.field, "new info"); }); it(`${controller.name} can check if pinned`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); let isPinned = await object.isPinned(); @@ -239,29 +241,34 @@ function runTest(controller) { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set('grandchild', grandchild); - parent.set('field', 'test'); - parent.set('child', child); + child.set("grandchild", grandchild); + parent.set("field", "test"); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(parent)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), true); + assert.equal( + localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), + true + ); assert.deepEqual(localDatastore[LDS_KEY(parent)], [parent._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(child)], [child._toFullJSON()]); - assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [grandchild._toFullJSON()]); + assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [ + grandchild._toFullJSON(), + ]); }); it(`${controller.name} can pin user (recursive)`, async () => { const parent = new TestObject(); const child = new Parse.User(); - child.setUsername('username'); - child.setPassword('password'); + child.setUsername("username"); + child.setPassword("password"); await child.signUp(); - parent.set('field', 'test'); - parent.set('child', child); + parent.set("field", "test"); + parent.set("child", child); await parent.save(); await parent.pin(); @@ -289,7 +296,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -298,7 +309,11 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -315,7 +330,11 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -327,11 +346,15 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); 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 +363,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()]); @@ -353,10 +380,14 @@ function runTest(controller) { const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + 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()]); @@ -367,8 +398,8 @@ function runTest(controller) { const obj2 = new TestObject(); await obj1.pin(); await obj2.pin(); - await obj1.pinWithName('test_pin'); - await obj2.pinWithName('test_pin'); + await obj1.pinWithName("test_pin"); + await obj2.pinWithName("test_pin"); await Parse.Object.saveAll([obj1, obj2]); @@ -376,8 +407,14 @@ function runTest(controller) { assert(Object.keys(localDatastore).length === 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); @@ -386,7 +423,9 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + LDS_KEY(obj2), + ]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -396,7 +435,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -404,9 +443,18 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -416,7 +464,9 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + LDS_KEY(obj2), + ]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -430,7 +480,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -439,7 +493,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -447,7 +504,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -462,7 +522,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -473,7 +537,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); }); @@ -522,7 +589,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -552,7 +623,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -576,7 +651,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -608,7 +687,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -629,27 +712,35 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); - await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); + await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); await Parse.Object.saveAll(objects); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -659,21 +750,27 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); + await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -683,16 +780,20 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); - await Parse.Object.unPinAllObjectsWithName('test_unpin'); + await Parse.Object.unPinAllObjectsWithName("test_unpin"); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); @@ -715,18 +816,22 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllObjectsWithName('test_unpin'); + await Parse.Object.unPinAllObjectsWithName("test_unpin"); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); @@ -740,7 +845,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -748,9 +853,18 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -766,11 +880,11 @@ function runTest(controller) { const obj2 = new TestObject(); const obj3 = new TestObject(); const child = new TestObject(); - obj1.set('child', child); + obj1.set("child", child); const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 6); @@ -778,10 +892,22 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(child)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(child)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -799,7 +925,7 @@ function runTest(controller) { const object = new TestObject(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); + assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); } }); @@ -809,7 +935,7 @@ function runTest(controller) { await object.pin(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); + assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); } }); @@ -817,8 +943,8 @@ function runTest(controller) { const obj1 = new TestObject(); const obj2 = new TestObject(); - obj1.set('field', 'test'); - obj1.set('foo', 'bar'); + obj1.set("field", "test"); + obj1.set("foo", "bar"); await obj1.pin(); await obj1.save(); @@ -833,10 +959,10 @@ function runTest(controller) { assert.deepEqual(obj1._toFullJSON(), obj3._toFullJSON()); const obj4 = TestObject.createWithoutData(obj1.id); - obj4.set('field', 'will not override'); + obj4.set("field", "will not override"); await obj4.fetchFromLocalDatastore(); - assert.equal(obj4.get('field'), 'will not override'); - assert.equal(obj4.get('foo'), 'bar'); + assert.equal(obj4.get("field"), "will not override"); + assert.equal(obj4.get("foo"), "bar"); }); it(`${controller.name} can fetchFromLocalDatastore with children`, async () => { @@ -845,14 +971,14 @@ function runTest(controller) { const child = new TestObject(); const grandchild = new TestObject(); - obj1.set('field', 'test'); - obj1.set('child', child); + obj1.set("field", "test"); + obj1.set("child", child); await obj1.save(); await obj1.pin(); - grandchild.set('field', 'shouldAlsoHave'); - child.set('field', 'shouldHave'); - child.set('grandchild', grandchild); + grandchild.set("field", "shouldAlsoHave"); + child.set("field", "shouldHave"); + child.set("grandchild", grandchild); await child.save(); obj2.id = obj1.id; @@ -860,16 +986,16 @@ function runTest(controller) { assert.deepEqual(obj1.toJSON(), obj2.toJSON()); assert.deepEqual(obj1._toFullJSON(), obj2._toFullJSON()); - assert.deepEqual(obj2.toJSON().child.field, 'shouldHave'); - assert.deepEqual(obj2.toJSON().child.grandchild.field, 'shouldAlsoHave'); + assert.deepEqual(obj2.toJSON().child.field, "shouldHave"); + assert.deepEqual(obj2.toJSON().child.grandchild.field, "shouldAlsoHave"); }); 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]); /* @@ -885,14 +1011,14 @@ function runTest(controller) { | C */ - A.set('B', B); - A.set('C', C); - A.set('E', E); - A.set('D', D); - B.set('A', A); - C.set('D', D); - D.set('C', C); - E.set('C', C); + A.set("B", B); + A.set("C", C); + A.set("E", E); + A.set("D", D); + B.set("A", A); + C.set("D", D); + D.set("C", C); + E.set("C", C); await Parse.Object.saveAll([A, B, C, D, E]); await A.pin(); @@ -902,23 +1028,23 @@ function runTest(controller) { await object.fetchFromLocalDatastore(); const root = object.toJSON(); - assert.deepEqual(root.B.A.__type, 'Pointer'); - assert.deepEqual(root.C.D.C.__type, 'Pointer'); - assert.deepEqual(root.E.C.__type, 'Object'); - assert.deepEqual(root.D.__type, 'Object'); + assert.deepEqual(root.B.A.__type, "Pointer"); + assert.deepEqual(root.C.D.C.__type, "Pointer"); + assert.deepEqual(root.E.C.__type, "Object"); + assert.deepEqual(root.D.__type, "Object"); }); - it('fetch updates LocalDatastore', async () => { - const item = new Item({ foo: 'bar' }); + it("fetch updates LocalDatastore", async () => { + const item = new Item({ foo: "bar" }); await item.save(); await item.pin(); const params = { id: item.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'bar'); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, "bar"); const itemAgain = new Item(); itemAgain.id = item.id; @@ -926,58 +1052,61 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(itemAgain.get('foo'), 'changed'); - assert.equal(fetchedItem.get('foo'), 'changed'); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'changed'); + assert.equal(itemAgain.get("foo"), "changed"); + assert.equal(fetchedItem.get("foo"), "changed"); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, "changed"); }); - it('fetchAll updates LocalDatastore', async () => { - const item1 = new Item({ foo: 'bar' }); - const item2 = new Item({ foo: 'baz' }); + it("fetchAll updates LocalDatastore", async () => { + const item1 = new Item({ foo: "bar" }); + const item2 = new Item({ foo: "baz" }); await Parse.Object.saveAll([item1, item2]); await Parse.Object.pinAll([item1, item2]); let params = { id: item1.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); params = { id: item2.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item1)][0].foo, 'bar'); - assert.equal(localDatastore[LDS_KEY(item2)][0].foo, 'baz'); + assert.equal(localDatastore[LDS_KEY(item1)][0].foo, "bar"); + assert.equal(localDatastore[LDS_KEY(item2)][0].foo, "baz"); const item1Again = new Item(); item1Again.id = item1.id; const item2Again = new Item(); item2Again.id = item2.id; - const fetchedItems = await Parse.Object.fetchAll([item1Again, item2Again]); + const fetchedItems = await Parse.Object.fetchAll([ + item1Again, + item2Again, + ]); localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(item1Again.get('foo'), 'changed'); - assert.equal(item2Again.get('foo'), 'changed'); - assert.equal(fetchedItems[0].get('foo'), 'changed'); - assert.equal(fetchedItems[1].get('foo'), 'changed'); - assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, 'changed'); - assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, 'changed'); + assert.equal(item1Again.get("foo"), "changed"); + assert.equal(item2Again.get("foo"), "changed"); + assert.equal(fetchedItems[0].get("foo"), "changed"); + assert.equal(fetchedItems[1].get("foo"), "changed"); + assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, "changed"); + assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, "changed"); }); it(`${controller.name} can update Local Datastore from network`, async () => { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set('grandchild', grandchild); - parent.set('field', 'test'); - parent.set('child', child); + child.set("grandchild", grandchild); + parent.set("field", "test"); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); // Updates child with { foo: 'changed' } const params = { id: child.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); Parse.LocalDatastore.isSyncing = false; @@ -985,7 +1114,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const childJSON = updatedLDS[LDS_KEY(child)]; - assert.equal(childJSON.foo, 'changed'); + assert.equal(childJSON.foo, "changed"); }); it(`${controller.name} can update Local Datastore from network ignore unsaved`, async () => { @@ -996,7 +1125,7 @@ function runTest(controller) { // Updates item with { foo: 'changed' } const params = { id: item.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); Parse.LocalDatastore.isSyncing = false; @@ -1004,19 +1133,19 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const itemJSON = updatedLDS[LDS_KEY(item)]; - assert.equal(itemJSON.foo, 'changed'); + assert.equal(itemJSON.foo, "changed"); }); it(`${controller.name} can update Local Datastore User from network`, async () => { const user = new Parse.User(); - user.setUsername('asdf'); - user.setPassword('zxcv'); + user.setUsername("asdf"); + user.setPassword("zxcv"); await user.signUp(); await user.pin(); // Updates user with { foo: 'changed' } const params = { id: user.id }; - await Parse.Cloud.run('UpdateUser', params); + await Parse.Cloud.run("UpdateUser", params); Parse.LocalDatastore.isSyncing = false; @@ -1024,7 +1153,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const userJSON = updatedLDS[LDS_KEY(user)]; - assert.equal(userJSON.foo, 'changed'); + assert.equal(userJSON.foo, "changed"); await Parse.User.logOut(); }); }); @@ -1039,7 +1168,7 @@ function runTest(controller) { const numbers = []; for (let i = 0; i < 10; i++) { - numbers[i] = new Parse.Object({ className: 'BoxedNumber', number: i }); + numbers[i] = new Parse.Object({ className: "BoxedNumber", number: i }); } await Parse.Object.saveAll(numbers); await Parse.Object.pinAll(numbers); @@ -1053,15 +1182,15 @@ function runTest(controller) { const objects = [obj1, obj2, obj3, item]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); const query = new Parse.Query(TestObject); - query.greaterThan('field', 1); - query.fromPinWithName('test_pin'); + query.greaterThan("field", 1); + query.fromPinWithName("test_pin"); const results = await query.find(); assert.equal(results.length, 2); - assert(results[0].get('field') > 1); - assert(results[1].get('field') > 1); + assert(results[0].get("field") > 1); + assert(results[1].get("field") > 1); }); it(`${controller.name} can query from local datastore`, async () => { @@ -1089,7 +1218,7 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); await obj4.save(); - await obj4.pinWithName('DO_NOT_QUERY'); + await obj4.pinWithName("DO_NOT_QUERY"); const query = new Parse.Query(TestObject); query.fromPin(); @@ -1099,7 +1228,7 @@ function runTest(controller) { }); it(`${controller.name} can query user from pin`, async () => { - const user = await Parse.User.signUp('asdf', 'zxcv', { foo: 'bar' }); + const user = await Parse.User.signUp("asdf", "zxcv", { foo: "bar" }); await user.pin(); const query = new Parse.Query(Parse.User); @@ -1112,22 +1241,22 @@ function runTest(controller) { }); it(`${controller.name} can do basic queries`, async () => { - const baz = new TestObject({ foo: 'baz' }); - const qux = new TestObject({ foo: 'qux' }); + const baz = new TestObject({ foo: "baz" }); + const qux = new TestObject({ foo: "qux" }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); - query.equalTo('foo', 'baz'); + query.equalTo("foo", "baz"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('foo'), 'baz'); + assert.equal(results[0].get("foo"), "baz"); }); it(`${controller.name} can do a query with a limit`, async () => { - const baz = new TestObject({ foo: 'baz' }); - const qux = new TestObject({ foo: 'qux' }); + const baz = new TestObject({ foo: "baz" }); + const qux = new TestObject({ foo: "qux" }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); @@ -1136,64 +1265,64 @@ function runTest(controller) { const results = await query.find(); assert.equal(results.length, 1); - assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); + assert.equal(["baz", "qux"].includes(results[0].get("foo")), true); }); it(`${controller.name} can do equalTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 3); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it('can do containedBy queries with numbers', async () => { + 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); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('containedBy', true); - query.containedBy('numbers', [1, 2, 3, 4, 5]); + query.equalTo("containedBy", true); + query.containedBy("numbers", [1, 2, 3, 4, 5]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it('can do containedBy queries with pointer', async () => { + it("can do containedBy queries with pointer", async () => { const objects = Array.from(Array(10).keys()).map((idx) => { - const obj = new Parse.Object('Object'); - obj.set('key', idx); + const obj = new Parse.Object("Object"); + obj.set("key", idx); return obj; }); - const parent1 = new Parse.Object('Parent'); - const parent2 = new Parse.Object('Parent'); - const parent3 = new Parse.Object('Parent'); + const parent1 = new Parse.Object("Parent"); + const parent2 = new Parse.Object("Parent"); + const parent3 = new Parse.Object("Parent"); await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); // [0, 1, 2] - parent1.set('objects', objects.slice(0, 3)); + parent1.set("objects", objects.slice(0, 3)); const shift = objects.shift(); // [2, 0] - parent2.set('objects', [objects[1], shift]); + parent2.set("objects", [objects[1], shift]); // [1, 2, 3, 4] - parent3.set('objects', objects.slice(1, 4)); + parent3.set("objects", objects.slice(1, 4)); await Parse.Object.saveAll([parent1, parent2, parent3]); await Parse.Object.pinAll([parent1, parent2, parent3]); - const query = new Parse.Query('Parent'); - query.containedBy('objects', objects); + const query = new Parse.Query("Parent"); + query.containedBy("objects", objects); query.fromLocalDatastore(); const results = await query.find(); @@ -1202,125 +1331,129 @@ function runTest(controller) { }); it(`${controller.name} can test equality with undefined`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', undefined); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", undefined); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} can perform lessThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThan("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 7); }); it(`${controller.name} can perform lessThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 8); }); it(`${controller.name} can perform greaterThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.greaterThan("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); }); it(`${controller.name} can perform greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.greaterThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 3); }); it(`${controller.name} can combine lessThanOrEqualTo and greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); - query.greaterThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThanOrEqualTo("number", 7); + query.greaterThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); it(`${controller.name} can combine lessThan and greaterThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 9); - query.greaterThan('number', 3); + const query = new Parse.Query("BoxedNumber"); + query.lessThan("number", 9); + query.greaterThan("number", 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); }); it(`${controller.name} can perform notEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.notEqualTo('number', 5); + const query = new Parse.Query("BoxedNumber"); + query.notEqualTo("number", 5); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 9); }); it(`${controller.name} can perform containedIn queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.containedIn('number', [3,5,7,9,11]); + const query = new Parse.Query("BoxedNumber"); + query.containedIn("number", [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 4); }); it(`${controller.name} can perform notContainedIn queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.notContainedIn('number', [3,5,7,9,11]); + const query = new Parse.Query("BoxedNumber"); + query.notContainedIn("number", [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 6); }); it(`${controller.name} can test objectId in containedIn queries`, async () => { - const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); - const ids = [numbers[2].id, numbers[3].id, 'nonsense']; - const query = new Parse.Query('BoxedNumber'); - query.containedIn('objectId', ids); - query.ascending('number'); + const numbers = await new Parse.Query("BoxedNumber") + .ascending("number") + .find(); + const ids = [numbers[2].id, numbers[3].id, "nonsense"]; + const query = new Parse.Query("BoxedNumber"); + query.containedIn("objectId", ids); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); - assert.equal(results[0].get('number'), 2); - assert.equal(results[1].get('number'), 3); + assert.equal(results[0].get("number"), 2); + assert.equal(results[1].get("number"), 3); }); it(`${controller.name} can test objectId in equalTo queries`, async () => { - const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); + const numbers = await new Parse.Query("BoxedNumber") + .ascending("number") + .find(); const id = numbers[5].id; - const query = new Parse.Query('BoxedNumber'); - query.equalTo('objectId', id); - query.ascending('number'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("objectId", id); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('number'), 5); + assert.equal(results[0].get("number"), 5); }); it(`${controller.name} can find no elements`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 15); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 15); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} handles when find throws errors`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); query.fromLocalDatastore(); try { await query.find(); @@ -1352,42 +1485,42 @@ 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); } }); it(`${controller.name} can query for the first result`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.descending('number'); + const query = new Parse.Query("BoxedNumber"); + query.descending("number"); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get('number'), 9); + assert.equal(result.get("number"), 9); }); it(`${controller.name} can query for the first with no results`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 20); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 20); query.fromLocalDatastore(); const result = await query.first(); assert.equal(result, undefined); }); 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); - query.equalTo('x', 44); + query.equalTo("x", 44); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get('x'), 44); + assert.equal(result.get("x"), 44); }); it(`${controller.name} handles when first throws errors`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); try { query.fromLocalDatastore(); await query.first(); @@ -1400,13 +1533,19 @@ 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); - const query = new Parse.Query('CoolContainer'); - query.notEqualTo('item', item1); + const query = new Parse.Query("CoolContainer"); + query.notEqualTo("item", item1); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -1422,14 +1561,14 @@ function runTest(controller) { await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); + query.equalTo("canSkip", true); query.skip(1); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); + query.equalTo("canSkip", true); query.skip(3); query.fromLocalDatastore(); results = await query.find(); @@ -1440,23 +1579,23 @@ 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); + query.equalTo("skipCount", true); query.fromLocalDatastore(); let count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); + query.equalTo("skipCount", true); query.skip(1); query.fromLocalDatastore(); count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); + query.equalTo("skipCount", true); query.skip(2); query.fromLocalDatastore(); count = await query.count(); @@ -1464,164 +1603,163 @@ function runTest(controller) { }); it(`${controller.name} can perform count queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 1); + 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); }); it(`${controller.name} can order by ascending numbers`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('number'); + const query = new Parse.Query("BoxedNumber"); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get('number'), 0); - assert.equal(results[9].get('number'), 9); + assert.equal(results[0].get("number"), 0); + assert.equal(results[9].get("number"), 9); }); it(`${controller.name} can order by descending numbers`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.descending('number'); + const query = new Parse.Query("BoxedNumber"); + query.descending("number"); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get('number'), 9); - assert.equal(results[9].get('number'), 0); + assert.equal(results[0].get("number"), 9); + assert.equal(results[9].get("number"), 0); }); it(`${controller.name} can order by ascending number then descending string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('doubleOrder', true); - query.ascending('number').addDescending('string'); + query.equalTo("doubleOrder", true); + query.ascending("number").addDescending("string"); query.fromLocalDatastore(); const results = await query.find(); 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'); + 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"); }); it(`${controller.name} can order by descending number then ascending string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('otherDoubleOrder', true); - query.descending('number').addAscending('string'); + query.equalTo("otherDoubleOrder", true); + query.descending("number").addAscending("string"); query.fromLocalDatastore(); const results = await query.find(); 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'); + 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"); }); it(`${controller.name} can order by descending number and string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number,string'); + query.equalTo("doubleDescending", true); + query.descending("number,string"); query.fromLocalDatastore(); let results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number, string'); + query.equalTo("doubleDescending", true); + query.descending("number, string"); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending(['number', 'string']); + query.equalTo("doubleDescending", true); + query.descending(["number", "string"]); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number', 'string'); + query.equalTo("doubleDescending", true); + query.descending("number", "string"); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); }); - it(`${controller.name} can not order by password`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('_password'); + const query = new Parse.Query("BoxedNumber"); + query.ascending("_password"); query.fromLocalDatastore(); try { await query.find(); @@ -1632,16 +1770,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate', true); - query.ascending('_created_at'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate", true); + query.ascending("_created_at"); query.fromLocalDatastore(); const results = await query.find(); @@ -1651,16 +1801,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate2', true); - query.descending('createdAt'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate2", true); + query.descending("createdAt"); query.fromLocalDatastore(); const results = await query.find(); @@ -1670,16 +1832,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate3', true); - query.ascending('_updated_at'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate3", true); + query.ascending("_updated_at"); query.fromLocalDatastore(); const results = await query.find(); @@ -1689,16 +1863,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate4', true); - query.ascending('updatedAt'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate4", true); + query.ascending("updatedAt"); query.fromLocalDatastore(); const results = await query.find(); @@ -1708,35 +1894,67 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('timed', true); - query.equalTo('createdAt', last.createdAt); + const query = new Parse.Query("TestObject"); + query.equalTo("timed", true); + query.equalTo("createdAt", last.createdAt); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'item4'); + assert.equal(results[0].get("name"), "item4"); }); 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]); - let query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.lessThan('createdAt', obj3.createdAt); - query.ascending('createdAt'); + let query = new Parse.Query("TestObject"); + query.equalTo("timed2", true); + query.lessThan("createdAt", obj3.createdAt); + query.ascending("createdAt"); query.fromLocalDatastore(); let results = await query.find(); @@ -1744,9 +1962,9 @@ function runTest(controller) { assert.equal(results[0].id, obj1.id); assert.equal(results[1].id, obj2.id); - query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.greaterThan('createdAt', obj3.createdAt); + query = new Parse.Query("TestObject"); + query.equalTo("timed2", true); + query.greaterThan("createdAt", obj3.createdAt); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); @@ -1755,43 +1973,43 @@ function runTest(controller) { it(`${controller.name} can test string matching`, async () => { const obj1 = new TestObject(); - obj1.set('myString', 'football'); + obj1.set("myString", "football"); const obj2 = new TestObject(); - obj2.set('myString', 'soccer'); + obj2.set("myString", "soccer"); await Parse.Object.saveAll([obj1, obj2]); await Parse.Object.pinAll([obj1, obj2]); let query = new Parse.Query(TestObject); - query.matches('myString', '^fo*\\wb[^o]l+$'); + query.matches("myString", "^fo*\\wb[^o]l+$"); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); + assert.equal(results[0].get("myString"), "football"); query = new Parse.Query(TestObject); - query.matches('myString', /^fo*\wb[^o]l+$/); + query.matches("myString", /^fo*\wb[^o]l+$/); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); + assert.equal(results[0].get("myString"), "football"); }); it(`${controller.name} can test case insensitive regex`, async () => { const obj = new TestObject(); - obj.set('myString', 'hockey'); + obj.set("myString", "hockey"); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.matches('myString', 'Hockey', 'i'); + query.matches("myString", "Hockey", "i"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'hockey'); + assert.equal(results[0].get("myString"), "hockey"); }); it(`${controller.name} fails for invalid regex options`, async () => { const query = new Parse.Query(TestObject); - query.matches('myString', 'football', 'some invalid thing'); + query.matches("myString", "football", "some invalid thing"); query.fromLocalDatastore(); try { await query.find(); @@ -1803,12 +2021,12 @@ function runTest(controller) { it(`${controller.name} can use a regex with all modifiers`, async () => { const obj = new TestObject(); - obj.set('website', '\n\nbuffer\n\nparse.COM'); + obj.set("website", "\n\nbuffer\n\nparse.COM"); await obj.save(); 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); @@ -1816,39 +2034,40 @@ function runTest(controller) { it(`${controller.name} can include regexp modifiers in the constructor`, async () => { const obj = new TestObject(); - obj.set('website', '\n\nbuffer\n\nparse.COM'); + obj.set("website", "\n\nbuffer\n\nparse.COM"); await obj.save(); 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); let query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); + query.equalTo("contains", true); + query.startsWith("myString", someAscii); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); + query.equalTo("contains", true); + query.startsWith("myString", someAscii); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 2); @@ -1859,9 +2078,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject(); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } objects.push(item); } @@ -1869,12 +2088,12 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.exists('y'); + query.exists("y"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); + assert(results[i].has("y")); } }); @@ -1883,9 +2102,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject({ dne: true }); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } objects.push(item); } @@ -1893,26 +2112,28 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('dne', true); - query.doesNotExist('y'); + query.equalTo("dne", true); + query.doesNotExist("y"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('z')); + assert(results[i].has("z")); } }); 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); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } objects.push(container); @@ -1920,27 +2141,27 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query('Container'); - query.equalTo('relation_exists', true); - query.exists('x'); + const query = new Parse.Query("Container"); + query.equalTo("relation_exists", true); + query.exists("x"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('x')); + assert(results[i].has("x")); } }); it(`${controller.name} can test if a relation does not exist`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const container = new Parse.Object('Container', { relation_dne: true }); + const container = new Parse.Object("Container", { relation_dne: true }); if (i % 2) { - container.set('y', i); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } objects.push(container); @@ -1948,14 +2169,14 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query('Container'); - query.equalTo('relation_dne', true); - query.doesNotExist('x'); + const query = new Parse.Query("Container"); + query.equalTo("relation_dne", true); + query.doesNotExist("x"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); + assert(results[i].has("y")); } }); @@ -1981,96 +2202,96 @@ function runTest(controller) { it(`${controller.name} can include nested objects`, async () => { const child = new TestObject(); - const parent = new Parse.Object('Container'); - child.set('foo', 'bar'); - parent.set('child', child); + const parent = new Parse.Object("Container"); + child.set("foo", "bar"); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include('child'); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); + query.include("child"); query.fromLocalDatastore(); const results = await query.find(); 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'); + assert(parentAgain.get("child")); + assert(parentAgain.get("child").id); + assert.equal(parentAgain.get("child").get("foo"), "bar"); }); it(`${controller.name} can includeAll nested objects`, async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); await Parse.Object.pinAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - assert.equal(parentAgain.get('child1').get('foo'), 'bar'); - assert.equal(parentAgain.get('child2').get('foo'), 'baz'); - assert.equal(parentAgain.get('child3').get('foo'), 'bin'); + assert.equal(parentAgain.get("child1").get("foo"), "bar"); + assert.equal(parentAgain.get("child2").get("foo"), "baz"); + assert.equal(parentAgain.get("child3").get("foo"), "bin"); }); it(`${controller.name} can includeAll nested objects in .each`, async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); query.fromLocalDatastore(); 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'); + assert.equal(obj.get("child1").get("foo"), "bar"); + assert.equal(obj.get("child2").get("foo"), "baz"); + assert.equal(obj.get("child3").get("foo"), "bin"); }); }); it(`${controller.name} can include nested objects via array`, async () => { const child = new TestObject(); - const parent = new Parse.Object('Container'); - child.set('foo', 'bar'); - parent.set('child', child); + const parent = new Parse.Object("Container"); + child.set("foo", "bar"); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include(['child']); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); + query.include(["child"]); query.fromLocalDatastore(); const results = await query.find(); 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'); + assert(parentAgain.get("child")); + assert(parentAgain.get("child").id); + assert.equal(parentAgain.get("child").get("foo"), "bar"); }); it(`${controller.name} can do a nested include`, async () => { - const Child = Parse.Object.extend('Child'); - const Parent = Parse.Object.extend('Parent'); - const Grandparent = Parse.Object.extend('Grandparent'); + const Child = Parse.Object.extend("Child"); + const Parent = Parse.Object.extend("Parent"); + const Grandparent = Parse.Object.extend("Grandparent"); const objects = []; for (let i = 0; i < 5; i++) { @@ -2080,7 +2301,7 @@ function runTest(controller) { parent: new Parent({ y: i, child: new Child({ - x: i + x: i, }), }), }); @@ -2091,315 +2312,327 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q = new Parse.Query('Grandparent'); - q.equalTo('nested', true); - q.include('parent.child'); + const q = new Parse.Query("Grandparent"); + q.equalTo("nested", true); + q.include("parent.child"); q.fromLocalDatastore(); const results = await q.find(); 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')); + assert.equal(o.get("z"), o.get("parent").get("y")); + assert.equal( + o.get("z"), + o + .get("parent") + .get("child") + .get("x") + ); }); }); it(`${controller.name} can include without changing dirty`, async () => { - const parent = new Parse.Object('ParentObject'); - const child = new Parse.Object('ChildObject'); - parent.set('child', child); - child.set('foo', 'bar'); + const parent = new Parse.Object("ParentObject"); + const child = new Parse.Object("ChildObject"); + parent.set("child", child); + child.set("foo", "bar"); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('ParentObject'); - query.include('child'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("ParentObject"); + query.include("child"); + query.equalTo("objectId", parent.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); + const childAgain = parentAgain.get("child"); assert.equal(child.id, childAgain.id); assert.equal(parent.id, parentAgain.id); - assert.equal(childAgain.get('foo'), 'bar'); + assert.equal(childAgain.get("foo"), "bar"); assert(!parentAgain.dirty()); assert(!childAgain.dirty()); }); it(`${controller.name} uses subclasses when creating objects`, async () => { - const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); - let ChildObject = Parse.Object.extend('ChildObject', { + const ParentObject = Parse.Object.extend({ className: "ParentObject" }); + let ChildObject = Parse.Object.extend("ChildObject", { foo() { - return 'foo'; - } + return "foo"; + }, }); const parent = new ParentObject(); const child = new ChildObject(); - parent.set('child', child); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - ChildObject = Parse.Object.extend('ChildObject', { + ChildObject = Parse.Object.extend("ChildObject", { bar() { - return 'bar'; - } + return "bar"; + }, }); const query = new Parse.Query(ParentObject); - query.equalTo('objectId', parent.id); - query.include('child'); + query.equalTo("objectId", parent.id); + query.include("child"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); - assert.equal(childAgain.foo(), 'foo'); - assert.equal(childAgain.bar(), 'bar'); + const childAgain = parentAgain.get("child"); + assert.equal(childAgain.foo(), "foo"); + assert.equal(childAgain.bar(), "bar"); }); it(`${controller.name} can match the results of another query`, async () => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('qtest', true); - subQuery.greaterThan('x', 5); + subQuery.equalTo("qtest", true); + subQuery.greaterThan("x", 5); const q = new Parse.Query(ParentObject); - q.matchesQuery('child', subQuery); + q.matchesQuery("child", subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 4); results.forEach((o) => { - assert(o.get('x') > 15); + assert(o.get("x") > 15); }); }); it(`${controller.name} can not match the results of another query`, async () => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('dneqtest', true); - subQuery.greaterThan('x', 5); + subQuery.equalTo("dneqtest", true); + subQuery.greaterThan("x", 5); const q = new Parse.Query(ParentObject); - q.equalTo('dneqtest', true); - q.doesNotMatchQuery('child', subQuery); + q.equalTo("dneqtest", true); + q.doesNotMatchQuery("child", subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 6); results.forEach((o) => { - assert(o.get('x') >= 10); - assert(o.get('x') <= 15); + assert(o.get("x") >= 10); + assert(o.get("x") <= 15); }); }); it(`${controller.name} can select keys from a matched query`, async () => { - const Restaurant = Parse.Object.extend('Restaurant'); - const Person = Parse.Object.extend('Person'); + const Restaurant = Parse.Object.extend("Restaurant"); + const Person = Parse.Object.extend("Person"); const objects = [ - new Restaurant({ rating: 5, location: 'Djibouti' }), - new Restaurant({ rating: 3, location: 'Ouagadougou' }), - new Person({ name: 'Bob', hometown: 'Djibouti' }), - new Person({ name: 'Tom', hometown: 'Ouagadougou' }), - new Person({ name: 'Billy', hometown: 'Detroit' }), + new Restaurant({ rating: 5, location: "Djibouti" }), + new Restaurant({ rating: 3, location: "Ouagadougou" }), + new Person({ name: "Bob", hometown: "Djibouti" }), + new Person({ name: "Tom", hometown: "Ouagadougou" }), + new Person({ name: "Billy", hometown: "Detroit" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); + query.greaterThan("rating", 4); let mainQuery = new Parse.Query(Person); - mainQuery.matchesKeyInQuery('hometown', 'location', query); + mainQuery.matchesKeyInQuery("hometown", "location", query); mainQuery.fromLocalDatastore(); let results = await mainQuery.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'Bob'); + assert.equal(results[0].get("name"), "Bob"); query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); + query.greaterThan("rating", 4); mainQuery = new Parse.Query(Person); - mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); - mainQuery.ascending('name'); + mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); + mainQuery.ascending("name"); mainQuery.fromLocalDatastore(); results = await mainQuery.find(); assert.equal(results.length, 2); - assert(['Billy', 'Tom'].includes(results[0].get('name'))); - assert(['Billy', 'Tom'].includes(results[1].get('name'))); + assert(["Billy", "Tom"].includes(results[0].get("name"))); + assert(["Billy", "Tom"].includes(results[1].get("name"))); }); - it(`${controller.name} supports objects with length`, async () => { + fit(`${controller.name} supports objects with length`, async () => { const obj = new TestObject(); - obj.set('length', 5); - assert.equal(obj.get('length'), 5); + obj.set("length", 5); + assert.equal(obj.get("length"), 5); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', obj.id); + query.equalTo("objectId", obj.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('length'), 5); + assert.equal(results[0].get("length"), 5); }); it(`${controller.name} can include User fields`, async () => { - const user = await Parse.User.signUp('bob', 'password', { age: 21 }); + const user = await Parse.User.signUp("bob", "password", { age: 21 }); const obj = new TestObject(); await obj.save({ owner: user }); await obj.pin(); const query = new Parse.Query(TestObject); - query.include('owner'); + query.include("owner"); query.fromLocalDatastore(); const objAgain = await query.get(obj.id); - assert(objAgain.get('owner') instanceof Parse.User); - assert.equal(objAgain.get('owner').get('age'), 21); + assert(objAgain.get("owner") instanceof Parse.User); + 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 () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object('BoxedNumber'); + const obj = new Parse.Object("BoxedNumber"); obj.set({ x: i, orquery: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('orquery', true); - q1.lessThan('x', 2); + 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 q2 = new Parse.Query("BoxedNumber"); + q2.equalTo("orquery", true); + q2.greaterThan("x", 5); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); const results = await orQuery.find(); assert.equal(results.length, 6); results.forEach((number) => { - assert(number.get('x') < 2 || number.get('x') > 5); + assert(number.get("x") < 2 || number.get("x") > 5); }); }); it(`${controller.name} can build complex OR queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object('Child'); - child.set('x', i); - child.set('complexor', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('complexor', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("complexor", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("complexor", true); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('complexor', true); + 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 q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('complexor', true); - q2.lessThan('y', 2); + const q2 = new Parse.Query("Parent"); + q2.equalTo("complexor", true); + q2.lessThan("y", 2); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); - const results = await orQuery.find(); + const results = await orQuery.find(); assert.equal(results.length, 3); }); it(`${controller.name} can build AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object('BoxedNumber'); + const obj = new Parse.Object("BoxedNumber"); obj.set({ x: i, and: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('and', true); - q1.greaterThan('x', 2); + 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 q2 = new Parse.Query("BoxedNumber"); + q2.equalTo("and", true); + q2.lessThan("x", 5); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); const results = await andQuery.find(); assert.equal(results.length, 2); results.forEach((number) => { - assert(number.get('x') > 2 && number.get('x') < 5); + assert(number.get("x") > 2 && number.get("x") < 5); }); }); it(`${controller.name} can build complex AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object('Child'); - child.set('x', i); - child.set('and', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('and', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("and", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("and", true); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('and', true); + 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 q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('and', true); - q2.equalTo('y', 4); + const q2 = new Parse.Query("Parent"); + q2.equalTo("and", true); + q2.equalTo("y", 4); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); @@ -2410,53 +2643,53 @@ function runTest(controller) { it(`${controller.name} can build NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const obj = new Parse.Object('NORTest'); + const obj = new Parse.Object("NORTest"); obj.set({ x: i }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('NORTest'); - q1.greaterThan('x', 5); - const q2 = new Parse.Query('NORTest'); - q2.lessThan('x', 3); + const q1 = new Parse.Query("NORTest"); + q1.greaterThan("x", 5); + const q2 = new Parse.Query("NORTest"); + q2.lessThan("x", 3); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 3); results.forEach((number) => { - assert(number.get('x') >= 3 && number.get('x') <= 5); + assert(number.get("x") >= 3 && number.get("x") <= 5); }); }); it(`${controller.name} can build complex NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const child = new Parse.Object('Child'); - child.set('x', i); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - const q1 = new Parse.Query('Parent'); - q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('y', 5); + const subQuery = new Parse.Query("Child"); + subQuery.equalTo("x", 4); + const q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); + const q2 = new Parse.Query("Parent"); + q2.equalTo("y", 5); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 8); results.forEach((number) => { - assert(number.get('x') !== 4 || number.get('x') !== 5); + assert(number.get("x") !== 4 || number.get("x") !== 5); }); }); @@ -2470,11 +2703,11 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.fromLocalDatastore(); await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); assert.equal(seen.length, 25); for (let i = 0; i < seen.length; i++) { @@ -2492,16 +2725,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - query.ascending('x'); + query.equalTo("eachtest", true); + query.lessThan("x", 25); + query.ascending("x"); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); @@ -2515,16 +2748,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.limit(20); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); @@ -2538,27 +2771,27 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.skip(20); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); it(`${controller.name} can select specific keys`, async () => { - const obj = new TestObject({ foo: 'baz', bar: 1 }); + const obj = new TestObject({ foo: "baz", bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); + q.equalTo("objectId", obj.id); + q.select("foo"); q.fromLocalDatastore(); const result = await q.first(); @@ -2566,23 +2799,23 @@ function runTest(controller) { assert(result.createdAt); assert(result.updatedAt); assert(!result.dirty()); - assert.equal(result.get('foo'), 'baz'); - assert.equal(result.get('bar'), undefined); + assert.equal(result.get("foo"), "baz"); + assert.equal(result.get("bar"), undefined); }); it(`${controller.name} can select specific keys with each`, async () => { - const obj = new TestObject({ foo: 'baz', bar: 1 }); + const obj = new TestObject({ foo: "baz", bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); + q.equalTo("objectId", obj.id); + q.select("foo"); q.fromLocalDatastore(); await q.each((o) => { assert(o.id); - assert.equal(o.get('foo'), 'baz'); - assert.equal(o.get('bar'), undefined); + assert.equal(o.get("foo"), "baz"); + assert.equal(o.get("bar"), undefined); }); }); @@ -2593,33 +2826,33 @@ function runTest(controller) { await obj.pin(); let q = new Parse.Query(TestObject); - q.equalTo('dateField', now); + q.equalTo("dateField", now); q.fromLocalDatastore(); let objects = await q.find(); assert.equal(objects.length, 1); const future = new Date(now.getTime() + 1000); q = new Parse.Query(TestObject); - q.lessThan('dateField', future); + q.lessThan("dateField", future); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.lessThanOrEqualTo('dateField', now); + q.lessThanOrEqualTo("dateField", now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); const past = new Date(now.getTime() - 1000); q = new Parse.Query(TestObject); - q.greaterThan('dateField', past); + q.greaterThan("dateField", past); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.greaterThanOrEqualTo('dateField', now); + q.greaterThanOrEqualTo("dateField", now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); @@ -2627,37 +2860,53 @@ 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('name', 'Sacramento'); + sacramento.set("location", new Parse.GeoPoint(38.52, -121.5)); + sacramento.set("name", "Sacramento"); const honolulu = new TestObject(); - honolulu.set('location', new Parse.GeoPoint(21.35, -157.93)); - honolulu.set('name', 'Honolulu'); + honolulu.set("location", new Parse.GeoPoint(21.35, -157.93)); + honolulu.set("name", "Honolulu"); const sf = new TestObject(); - sf.set('location', new Parse.GeoPoint(37.75, -122.68)); - sf.set('name', 'San Francisco'); + sf.set("location", new Parse.GeoPoint(37.75, -122.68)); + sf.set("name", "San Francisco"); await Parse.Object.saveAll([sacramento, honolulu, sf]); await Parse.Object.pinAll([sacramento, honolulu, sf]); 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); + query.withinPolygon("location", points); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); 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); @@ -2672,7 +2921,7 @@ function runTest(controller) { const point = new Parse.GeoPoint(0.5, 0.5); const query = new Parse.Query(TestObject); - query.polygonContains('polygon', point); + query.polygonContains("polygon", point); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); @@ -2681,69 +2930,90 @@ function runTest(controller) { it(`${controller.name} can query from pin subclass`, async () => { class ClassA extends Parse.Object { constructor() { - super('ClassA'); + 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); + Parse.Object.registerSubclass("ClassA", ClassA); class ClassB extends Parse.Object { constructor() { - super('ClassB'); + 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); + Parse.Object.registerSubclass("ClassB", ClassB); const testClassA = new ClassA(); - testClassA.name = 'ABC'; + testClassA.name = "ABC"; await testClassA.pin(); const query = new Parse.Query(ClassA); query.fromLocalDatastore(); - query.equalTo('name', 'ABC'); + query.equalTo("name", "ABC"); const result = await query.first(); - expect(result.get('name')).toBe('ABC'); + expect(result.get("name")).toBe("ABC"); const testClassB = new ClassB(); - testClassB.name = 'XYZ'; + testClassB.name = "XYZ"; testClassB.classA = testClassA; await testClassB.pin(); let localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual(testClassA.toOfflinePointer()); + expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual( + testClassA.toOfflinePointer() + ); await testClassB.save(); expect(testClassB.classA).toBe(testClassA); expect(testClassA.id).toBeDefined(); localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual(testClassA.id); + expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual( + testClassA.id + ); }); }); } -describe('Parse LocalDatastore', () => { +describe("Parse LocalDatastore", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); - Parse.CoreManager.getInstallationController()._setInstallationIdCache('1234'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.CoreManager.getInstallationController()._setInstallationIdCache( + "1234" + ); Parse.enableLocalDatastore(); 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: "Default", file: "../../lib/node/LocalDatastoreController" }, + { + name: "React-Native", + file: "../../lib/node/LocalDatastoreController.react-native", + }, ]; for (let i = 0; i < controllers.length; i += 1) { diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index e9d338bb9..b84115fd2 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -1,10 +1,10 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); class CustomUser extends Parse.User { constructor(attributes) { @@ -15,16 +15,16 @@ class CustomUser extends Parse.User { return 5; } } -Parse.Object.registerSubclass('CustomUser', CustomUser); +Parse.Object.registerSubclass("CustomUser", CustomUser); const provider = { authenticate: () => Promise.resolve(), restoreAuthentication: () => true, - getAuthType: () => 'anonymous', + getAuthType: () => "anonymous", getAuthData() { return { authData: { - id: '1234', + id: "1234", }, }; }, @@ -32,9 +32,9 @@ const provider = { Parse.User._registerAuthenticationProvider(provider); const authResponse = { - userID: 'test', - accessToken: 'test', - expiresIn: 'test', // Should be unix timestamp + userID: "test", + accessToken: "test", + expiresIn: "test", // Should be unix timestamp }; global.FB = { init: () => {}, @@ -44,38 +44,42 @@ global.FB = { getAuthResponse: () => authResponse, }; -describe('Parse User', () => { +describe("Parse User", () => { beforeAll(() => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); - Parse.Object.registerSubclass('_User', Parse.User); + Parse.Object.registerSubclass("_User", Parse.User); }); 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.setPassword("asdf"); + user.setUsername("zxcv"); user.signUp().then((user) => { assert(user.getSessionToken()); expect(user.existed()).toBe(false); @@ -83,467 +87,541 @@ describe('Parse User', () => { }); }); - 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 () => { + it("can login users with installationId", async () => { Parse.User.enableUnsafeCurrentUser(); const currentInstallation = await Parse.CoreManager.getInstallationController().currentInstallationId(); - const installationId = '12345678'; + const installationId = "12345678"; const user = new Parse.User(); - user.set('username', 'parse'); - user.set('password', 'mypass'); + user.set("username", "parse"); + user.set("password", "mypass"); await user.signUp(null, { installationId }); const query = new Parse.Query(Parse.Session); - query.equalTo('user', user); + query.equalTo("user", user); const result = await query.first({ useMasterKey: true }); - expect(result.get('installationId')).toBe(installationId); - expect(result.get('sessionToken')).toBe(user.getSessionToken()); + expect(result.get("installationId")).toBe(installationId); + expect(result.get("sessionToken")).toBe(user.getSessionToken()); // Should not clean up sessions - const loggedUser = await Parse.User.logIn('parse', 'mypass'); + const loggedUser = await Parse.User.logIn("parse", "mypass"); const sessionQuery = new Parse.Query(Parse.Session); let sessions = await sessionQuery.find({ useMasterKey: true }); expect(sessions.length).toBe(2); - expect(sessions[0].get('installationId')).toBe(installationId); - expect(sessions[1].get('installationId')).toBe(currentInstallation); - expect(sessions[0].get('sessionToken')).toBe(user.getSessionToken()); - expect(sessions[1].get('sessionToken')).toBe(loggedUser.getSessionToken()); + expect(sessions[0].get("installationId")).toBe(installationId); + expect(sessions[1].get("installationId")).toBe(currentInstallation); + expect(sessions[0].get("sessionToken")).toBe(user.getSessionToken()); + 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); - expect(sessions[1].get('installationId')).toBe(installationId); - expect(sessions[0].get('sessionToken')).toBe(loggedUser.getSessionToken()); - expect(sessions[1].get('sessionToken')).toBe(installationUser.getSessionToken()); + expect(sessions[0].get("installationId")).toBe(currentInstallation); + expect(sessions[1].get("installationId")).toBe(installationId); + expect(sessions[0].get("sessionToken")).toBe(loggedUser.getSessionToken()); + 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({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', + password: "asdf", + 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 () => { + it("can fetch non-auth user with include", async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object('TestObject'); - child.set('field', 'test'); + const child = new Parse.Object("TestObject"); + child.set("field", "test"); const user = new Parse.User(); - user.set('password', 'asdf'); - user.set('email', 'asdf@exxample.com'); - user.set('username', 'zxcv'); - user.set('child', child); + user.set("password", "asdf"); + user.set("email", "asdf@exxample.com"); + user.set("username", "zxcv"); + user.set("child", child); await user.signUp(); const query = new Parse.Query(Parse.User); const userNotAuthed = await query.get(user.id); - assert.equal(userNotAuthed.get('child').get('field'), undefined); + assert.equal(userNotAuthed.get("child").get("field"), undefined); - const fetchedUser = await userNotAuthed.fetchWithInclude('child'); + const fetchedUser = await userNotAuthed.fetchWithInclude("child"); - assert.equal(userNotAuthed.get('child').get('field'), 'test'); - assert.equal(fetchedUser.get('child').get('field'), 'test'); + assert.equal(userNotAuthed.get("child").get("field"), "test"); + assert.equal(fetchedUser.get("child").get("field"), "test"); }); - it('can fetch auth user with include', async () => { + it("can fetch auth user with include", async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object('TestObject'); - child.set('field', 'test'); + const child = new Parse.Object("TestObject"); + child.set("field", "test"); let user = new Parse.User(); - user.set('password', 'asdf'); - user.set('email', 'asdf@exxample.com'); - user.set('username', 'zxcv'); - user.set('child', child); + user.set("password", "asdf"); + user.set("email", "asdf@exxample.com"); + user.set("username", "zxcv"); + user.set("child", child); await user.signUp(); - user = await Parse.User.logIn('zxcv', 'asdf'); + user = await Parse.User.logIn("zxcv", "asdf"); - assert.equal(user.get('child').get('field'), undefined); - assert.equal(Parse.User.current().get('child').get('field'), undefined); + assert.equal(user.get("child").get("field"), undefined); + assert.equal( + Parse.User.current() + .get("child") + .get("field"), + undefined + ); - const fetchedUser = await user.fetchWithInclude('child'); + const fetchedUser = await user.fetchWithInclude("child"); const current = await Parse.User.currentAsync(); - assert.equal(user.get('child').get('field'), 'test'); - assert.equal(current.get('child').get('field'), 'test'); - assert.equal(fetchedUser.get('child').get('field'), 'test'); - assert.equal(Parse.User.current().get('child').get('field'), 'test'); + assert.equal(user.get("child").get("field"), "test"); + assert.equal(current.get("child").get("field"), "test"); + assert.equal(fetchedUser.get("child").get("field"), "test"); + 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.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(); + }); }); - 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(); const user3 = new Parse.User(); - user1.set('username', 'a'); - user2.set('username', 'b'); - user3.set('username', 'c'); - - user1.set('password', 'password'); - 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.set("username", "a"); + user2.set("username", "b"); + user3.set("username", "c"); + + user1.set("password", "password"); + 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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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) => { - const SuperUser = Parse.Object.extend('User'); + it("handles user subclassing", (done) => { + const SuperUser = Parse.Object.extend("User"); const user = new SuperUser(); - user.set('username', 'bob'); - user.set('password', 'welcome'); + user.set("username", "bob"); + user.set("password", "welcome"); assert(user instanceof Parse.User); user.signUp().then(() => { done(); }); }); - 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(); }); }); - it('can save anonymous user', async () => { + it("can save anonymous user", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello'); + user.set("field", "hello"); await user.save(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get('field')).toBe('hello'); + expect(result.get("field")).toBe("hello"); }); - it('can not recover anonymous user if logged out', async () => { + it("can not recover anonymous user if logged out", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello'); + user.set("field", "hello"); await user.save(); await Parse.User.logOut(); @@ -552,75 +630,75 @@ describe('Parse User', () => { try { await query.get(user.id); } catch (error) { - expect(error.message).toBe('Object not found.'); + expect(error.message).toBe("Object not found."); } }); - it('can signUp anonymous user and retain data', async () => { + it("can signUp anonymous user and retain data", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello world'); + user.set("field", "hello world"); await user.save(); - expect(user.get('authData').anonymous).toBeDefined(); + expect(user.get("authData").anonymous).toBeDefined(); - user.setUsername('foo'); - user.setPassword('baz'); + user.setUsername("foo"); + user.setPassword("baz"); await user.signUp(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get('username')).toBe('foo'); - expect(result.get('authData')).toBeUndefined(); - expect(result.get('field')).toBe('hello world'); - expect(user.get('authData').anonymous).toBeUndefined(); + expect(result.get("username")).toBe("foo"); + expect(result.get("authData")).toBeUndefined(); + expect(result.get("field")).toBe("hello world"); + expect(user.get("authData").anonymous).toBeUndefined(); }); - it('can logIn user without converting anonymous user', async () => { + it("can logIn user without converting anonymous user", async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp('foobaz', '1234'); + await Parse.User.signUp("foobaz", "1234"); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello world'); + user.set("field", "hello world"); await user.save(); - await Parse.User.logIn('foobaz', '1234'); + await Parse.User.logIn("foobaz", "1234"); const query = new Parse.Query(Parse.User); try { await query.get(user.id); } catch (error) { - expect(error.message).toBe('Object not found.'); + expect(error.message).toBe("Object not found."); } }); - it('anonymous user logIn does not use currentUser sessionToken', async () => { + it("anonymous user logIn does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = await Parse.AnonymousUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('anonymous user link currentUser', async () => { + it("anonymous user link currentUser", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = await Parse.AnonymousUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it('anonymous user link does not use currentUser sessionToken', async () => { + it("anonymous user link does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = new Parse.User(); await Parse.AnonymousUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -628,33 +706,33 @@ describe('Parse User', () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('facebook logIn does not use currentUser sessionToken', async () => { + it("facebook logIn does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = await Parse.FacebookUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('facebook link currentUser', async () => { + it("facebook link currentUser", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = await Parse.FacebookUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it('facebook link does not use currentUser sessionToken', async () => { + it("facebook link does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = new Parse.User(); await Parse.FacebookUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -662,27 +740,27 @@ describe('Parse User', () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('can signUp user with subclass', async () => { + it("can signUp user with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); const user = await customUser.signUp(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can get current with subclass', async () => { + it("can get current with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - Parse.Object.registerSubclass('_User', CustomUser); + Parse.Object.registerSubclass("_User", CustomUser); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); await customUser.signUp(); Parse.User._clearCache(); @@ -690,91 +768,94 @@ describe('Parse User', () => { const user = CustomUser.current(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can logIn user with subclass', async () => { + it("can logIn user with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp('username', 'password'); + await Parse.User.signUp("username", "password"); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); const user = await customUser.logIn(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can signUp / logIn user with subclass static', async () => { + it("can signUp / logIn user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + let user = await CustomUser.signUp("username", "password"); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - user = await CustomUser.logIn('username', 'password'); + user = await CustomUser.logIn("username", "password"); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can become user with subclass static', async () => { + it("can become user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + 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); }); - it('can get user (me) with subclass static', async () => { + it("can get user (me) with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + 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); }); - it('can get hydrate user with subclass static', async () => { + it("can get hydrate user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await CustomUser.hydrate({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc', + objectId: "uid3", + username: "username", + sessionToken: "123abc", }); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can loginWith subclass static', async () => { + it("can loginWith subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); let user = new CustomUser(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - user = await CustomUser.logInWith(provider.getAuthType(), provider.getAuthData()); + user = await CustomUser.logInWith( + provider.getAuthType(), + provider.getAuthData() + ); expect(user._isLinked(provider)).toBe(true); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can link without master key', async () => { + it("can link without master key", async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -782,58 +863,67 @@ describe('Parse User', () => { expect(user._isLinked(provider)).toBe(false); }); - it('can link with master key', async () => { + it("can link with master key", async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + 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); }); - it('can link with session token', async () => { + it("can link with session token", async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); 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); }); - it('linked account can login with authData', async () => { + it("linked account can login with authData", async () => { const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + 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(); - const loggedIn = await Parse.User.logInWith(provider.getAuthType(), provider.getAuthData()); + const loggedIn = await Parse.User.logInWith( + provider.getAuthType(), + provider.getAuthData() + ); expect(loggedIn.authenticated()).toBeTruthy(); }); - it('can linking un-authenticated user without master key', async () => { + it("can linking un-authenticated user without master key", async () => { const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.save(null, { useMasterKey: true }); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user.getSessionToken()).toBeDefined(); }); - it('can link with custom auth', async () => { + it("can link with custom auth", async () => { Parse.User.enableUnsafeCurrentUser(); const provider = { authenticate: () => Promise.resolve(), @@ -842,7 +932,7 @@ describe('Parse User', () => { }, getAuthType() { - return 'myAuth'; + return "myAuth"; }, getAuthData() { @@ -855,8 +945,8 @@ describe('Parse User', () => { }; Parse.User._registerAuthenticationProvider(provider); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -864,19 +954,19 @@ describe('Parse User', () => { expect(user._isLinked(provider)).toBe(false); }); - it('can login with facebook', async () => { + it("can login with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.FacebookUtils.logIn(); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); }); - it('can link user with facebook', async () => { + it("can link user with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); @@ -884,7 +974,7 @@ describe('Parse User', () => { expect(Parse.FacebookUtils.isLinked(user)).toBe(false); }); - it('can link anonymous user with facebook', async () => { + it("can link anonymous user with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.AnonymousUtils.logIn(); @@ -898,30 +988,30 @@ describe('Parse User', () => { expect(Parse.AnonymousUtils.isLinked(user)).toBe(true); }); - it('can link with twitter', async () => { + it("can link with twitter", async () => { Parse.User.enableUnsafeCurrentUser(); const authData = { id: 227463280, consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr", }; const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - await user.linkWith('twitter', { authData }); + await user.linkWith("twitter", { authData }); - expect(user.get('authData').twitter.id).toBe(authData.id); - expect(user._isLinked('twitter')).toBe(true); + expect(user.get("authData").twitter.id).toBe(authData.id); + expect(user._isLinked("twitter")).toBe(true); - await user._unlinkFrom('twitter'); - expect(user._isLinked('twitter')).toBe(false); + await user._unlinkFrom("twitter"); + expect(user._isLinked("twitter")).toBe(false); }); - it('can link with twitter and facebook', async () => { + it("can link with twitter and facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const authData = { @@ -929,65 +1019,68 @@ describe('Parse User', () => { consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr", }; const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - await user.linkWith('twitter', { authData }); + await user.linkWith("twitter", { authData }); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); - expect(user._isLinked('twitter')).toBe(true); + expect(user._isLinked("twitter")).toBe(true); - expect(user.get('authData').twitter.id).toBe(authData.id); - expect(user.get('authData').facebook.id).toBe('test'); + expect(user.get("authData").twitter.id).toBe(authData.id); + expect(user.get("authData").facebook.id).toBe("test"); }); - it('can verify user password via static method', async () => { - await Parse.User.signUp('asd123', 'xyz123'); - const res = await Parse.User.verifyPassword('asd123', 'xyz123'); - expect(typeof res).toBe('object'); - expect(res.username).toBe('asd123'); + it("can verify user password via static method", async () => { + await Parse.User.signUp("asd123", "xyz123"); + const res = await Parse.User.verifyPassword("asd123", "xyz123"); + expect(typeof res).toBe("object"); + expect(res.username).toBe("asd123"); try { - await Parse.User.verifyPassword('asd123', 'wrong password'); + await Parse.User.verifyPassword("asd123", "wrong password"); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe('Invalid username/password.'); + expect(error.message).toBe("Invalid username/password."); } }); - it('can verify user password via instance method', async () => { - const user = await Parse.User.signUp('asd123', 'xyz123'); - const res = await user.verifyPassword('xyz123'); - expect(typeof res).toBe('object'); - expect(res.username).toBe('asd123'); + it("can verify user password via instance method", async () => { + const user = await Parse.User.signUp("asd123", "xyz123"); + const res = await user.verifyPassword("xyz123"); + expect(typeof res).toBe("object"); + expect(res.username).toBe("asd123"); try { - await user.verifyPassword('wrong password'); + await user.verifyPassword("wrong password"); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe('Invalid username/password.'); + expect(error.message).toBe("Invalid username/password."); } }); - it('can encrypt user', async () => { + it("can encrypt user", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.enableEncryptedUser(); - Parse.secret = 'My Secret Key'; + Parse.secret = "My Secret Key"; const user = new Parse.User(); - user.setUsername('usernameENC'); - user.setPassword('passwordENC'); + user.setUsername("usernameENC"); + user.setPassword("passwordENC"); await user.signUp(); - const path = Parse.Storage.generatePath('currentUser'); + const path = Parse.Storage.generatePath("currentUser"); const encryptedUser = Parse.Storage.getItem(path); const crypto = Parse.CoreManager.getCryptoController(); - const decryptedUser = crypto.decrypt(encryptedUser, Parse.CoreManager.get('ENCRYPTED_KEY')); + const decryptedUser = crypto.decrypt( + encryptedUser, + Parse.CoreManager.get("ENCRYPTED_KEY") + ); expect(JSON.parse(decryptedUser).objectId).toBe(user.id); const currentUser = Parse.User.current(); @@ -996,22 +1089,22 @@ describe('Parse User', () => { const currentUserAsync = await Parse.User.currentAsync(); expect(currentUserAsync).toEqual(user); await Parse.User.logOut(); - Parse.CoreManager.set('ENCRYPTED_USER', false); - Parse.CoreManager.set('ENCRYPTED_KEY', null); + Parse.CoreManager.set("ENCRYPTED_USER", false); + Parse.CoreManager.set("ENCRYPTED_KEY", null); }); - it('fix GHSA-wvh7-5p38-2qfc', async () => { + it("fix GHSA-wvh7-5p38-2qfc", async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('username'); - user.setPassword('password'); + user.setUsername("username"); + user.setPassword("password"); await user.signUp(); - const path = Parse.Storage.generatePath('currentUser'); + const path = Parse.Storage.generatePath("currentUser"); let userData = Parse.Storage.getItem(path); expect(JSON.parse(userData).password).toBeUndefined(); - user.setPassword('password'); + user.setPassword("password"); await user.save(null, { useMasterKey: true }); userData = Parse.Storage.getItem(path); diff --git a/jasmine.json b/jasmine.json index a7eb69d0e..cf2635979 100644 --- a/jasmine.json +++ b/jasmine.json @@ -1,11 +1,7 @@ { "spec_dir": "integration/test", - "helpers": [ - "helper.js" - ], - "spec_files": [ - "*Test.js" - ], + "helpers": ["helper.js"], + "spec_files": ["*Test.js"], "random": false, "timeout": 5000 } diff --git a/package-lock.json b/package-lock.json index 0c47ceb52..7be0da87b 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,131 +1349,27 @@ } } }, - "@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", "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==", "dev": true }, + "@hapi/hoek": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.0.tgz", + "integrity": "sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==", + "dev": true + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@jest/console": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", @@ -1744,119 +1599,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 +1671,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", @@ -2106,6 +1744,27 @@ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", "dev": true }, + "@sideway/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.0.tgz", + "integrity": "sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2574,6 +2233,81 @@ "uri-js": "^4.2.2" } }, + "ampersand-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz", + "integrity": "sha1-9AK8LhgwX6vZldvc07cFe73X00c=", + "dev": true, + "requires": { + "ampersand-version": "^1.0.2", + "lodash": "^4.6.1" + } + }, + "ampersand-state": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz", + "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==", + "dev": true, + "requires": { + "ampersand-events": "^2.0.1", + "ampersand-version": "^1.0.0", + "array-next": "~0.0.1", + "key-tree-store": "^1.3.0", + "lodash": "^4.12.0" + } + }, + "ampersand-version": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz", + "integrity": "sha1-/489TOrE0yzNg/a9Zpc5f3tZ4sA=", + "dev": true, + "requires": { + "find-root": "^0.1.1", + "through2": "^0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", + "dev": true + }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -2640,16 +2374,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 +2384,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 +2418,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 +2427,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 +2443,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", @@ -3072,6 +2601,12 @@ } } }, + "array-next": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz", + "integrity": "sha1-5eRmCkwn/agVH/d2QnXQCQAGK+E=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -3672,6 +3207,12 @@ } } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3947,6 +3488,28 @@ "ieee754": "^1.1.4" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", @@ -3959,6 +3522,12 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", "dev": true }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4103,6 +3672,18 @@ "lodash": "^4.17.14" } }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4120,6 +3701,36 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -4208,6 +3819,29 @@ } } }, + "cli-color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", + "integrity": "sha1-dfpfcowwjMSsWUsF4GzF2A2szYY=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.2", + "memoizee": "0.3.x", + "timers-ext": "0.1.x" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4300,6 +3934,15 @@ "readable-stream": "^2.3.5" } }, + "clui": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz", + "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==", + "dev": true, + "requires": { + "cli-color": "0.3.2" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4468,6 +4111,22 @@ "typedarray": "^0.0.6" } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=", + "dev": true + }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -4724,7 +4383,26 @@ "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 + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true }, "cssfilter": { "version": "0.0.10", @@ -4829,41 +4507,170 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "deepcopy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.1.0.tgz", - "integrity": "sha512-8cZeTb1ZKC3bdSCP6XOM1IsTczIO73fdqtwa2B0N15eAz7gmyhQo+mc5gnFuulsgN3vIQYmTgbmQVKalH1dKvQ==", - "dev": true, - "requires": { - "type-detect": "^4.0.8" - } - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", "dev": true, "requires": { - "kind-of": "^5.0.2" + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepcopy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.1.0.tgz", + "integrity": "sha512-8cZeTb1ZKC3bdSCP6XOM1IsTczIO73fdqtwa2B0N15eAz7gmyhQo+mc5gnFuulsgN3vIQYmTgbmQVKalH1dKvQ==", + "dev": true, + "requires": { + "type-detect": "^4.0.8" + } + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", "dev": true }, @@ -5214,6 +5021,12 @@ } } }, + "docopt": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", + "integrity": "sha1-so6eIiDaXsSffqW7JKR3h0Be6xE=", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5223,12 +5036,28 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", @@ -5238,6 +5067,108 @@ "webidl-conversions": "^4.0.2" } }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "downcache": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/downcache/-/downcache-0.0.9.tgz", + "integrity": "sha1-eQuwQkaJE2EVzpPyqhWUbG2AbQ4=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "graceful-fs": "^4.1.3", + "limiter": "^1.1.0", + "mkdirp": "^0.5.1", + "npmlog": "^2.0.3", + "request": "^2.69.0", + "rimraf": "^2.5.2" + }, + "dependencies": { + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "dev": true, + "requires": { + "ansi": "^0.3.0", + "has-unicode": "^2.0.0", + "lodash.pad": "^4.1.0", + "lodash.padend": "^4.1.0", + "lodash.padstart": "^4.1.0" + } + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "dev": true, + "requires": { + "ansi": "~0.3.1", + "are-we-there-yet": "~1.1.2", + "gauge": "~1.2.5" + } + } + } + }, + "download": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", + "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", + "dev": true, + "requires": { + "caw": "^2.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.0.0", + "ext-name": "^5.0.0", + "file-type": "5.2.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^7.0.0", + "make-dir": "^1.0.0", + "p-event": "^1.0.0", + "pify": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + } + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -5247,6 +5178,12 @@ "readable-stream": "^2.0.2" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -5745,6 +5682,32 @@ "es5-ext": "~0.10.14" } }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + }, + "dependencies": { + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + } + } + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -5990,6 +5953,25 @@ } } }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6150,6 +6132,15 @@ "bser": "2.1.1" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "fecha": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", @@ -6183,6 +6174,12 @@ "moment": "^2.11.2" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -6195,6 +6192,23 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -6250,6 +6264,12 @@ } } }, + "find-root": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz", + "integrity": "sha1-mNImfP8ZFsyvJ0OzoO6oHXnX3NE=", + "dev": true + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -6391,12 +6411,35 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, "fs-capacitor": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-mkdirp-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", @@ -6543,6 +6586,27 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-mongodb-version": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-2.0.1.tgz", + "integrity": "sha512-yTN0UY7VJSSt01QH/aCiqiBjfxcDrEdKeM3uXY6QR3sRARoftx36QT0YNsCQm7FDTgrmDje7bK2C9ClM7SGKDA==", + "dev": true, + "requires": { + "lodash.startswith": "^4.2.1", + "minimist": "^1.1.1", + "mongodb": "*", + "which": "^1.1.1" + } + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "requires": { + "npm-conf": "^1.1.0" + } + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -6758,6 +6822,36 @@ "sparkles": "^1.0.0" } }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "requires": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -6770,30 +6864,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", @@ -7239,12 +7309,27 @@ "sparkles": "^1.0.0" } }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -7379,6 +7464,33 @@ "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -7446,6 +7558,12 @@ } } }, + "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 + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -7836,11 +7954,44 @@ "is-extglob": "^2.1.1" } }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true + "is-mongodb-running": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-1.0.2.tgz", + "integrity": "sha512-EslN8MErcBPExb+iK4RnG1n28JGjByA2Rm3YPmdHDGCRd7Hc2uvqshyVMAJXxbDSxRMy8vhxims2oRqQUeGJeA==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "debug": ">= 2.6.9", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "lsof": "^0.1.0", + "minimist": "^1.2.0", + "node-netstat": "^1.4.2", + "ps-node": "^0.1.6" + }, + "dependencies": { + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + } + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true }, "is-negative-zero": { "version": "2.0.0", @@ -7868,6 +8019,18 @@ } } }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -7913,6 +8076,12 @@ "is-unc-path": "^1.0.0" } }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -8072,6 +8241,16 @@ "html-escaper": "^2.0.0" } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "iterall": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", @@ -8756,6 +8935,19 @@ "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", "dev": true }, + "joi": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.3.0.tgz", + "integrity": "sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8944,6 +9136,15 @@ "minimist": "^1.2.5" } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -9003,21 +9204,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", @@ -9028,6 +9214,12 @@ "safe-buffer": "^5.0.1" } }, + "key-tree-store": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz", + "integrity": "sha1-XqKa/CUppCWThDfWlVtxTOapeR8=", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -9075,6 +9267,12 @@ "es6-weak-map": "^2.0.1" } }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -9102,22 +9300,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", @@ -9217,12 +9399,54 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", + "dev": true + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", + "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.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", + "dev": true + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -9259,24 +9483,84 @@ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", "dev": true }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "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 }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "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 }, + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", + "dev": true + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.startswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", + "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=", + "dev": true + }, "logform": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", @@ -9328,6 +9612,12 @@ } } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -9367,6 +9657,21 @@ } } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "lsof": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz", + "integrity": "sha1-rALU2HYGIB8TZLr7FcSRz9WuMJI=", + "dev": true + }, "mailgun-js": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", @@ -9458,6 +9763,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -9556,6 +9867,71 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "memoizee": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", + "integrity": "sha1-TsoNiu057J0Bf0xcLy9kMvQuXI8=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.11", + "es6-weak-map": "~0.1.4", + "event-emitter": "~0.3.4", + "lru-queue": "0.1", + "next-tick": "~0.2.2", + "timers-ext": "0.1" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5", + "es6-symbol": "~2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5" + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.6", + "es6-iterator": "~0.1.3", + "es6-symbol": "~2.0.1" + } + }, + "next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=", + "dev": true + } + } + }, "memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -9693,6 +10069,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -9810,263 +10192,577 @@ "saslprep": "^1.0.0" } }, - "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 - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "mongodb-core": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.7.tgz", + "integrity": "sha512-WypKdLxFNPOH/Jy6i9z47IjG2wIldA54iDZBmHMINcgKOUcWJh8og+Wix76oGd7EyYkHJKssQ2FAOw5Su/n4XQ==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" } }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "mongodb-dbpath": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz", + "integrity": "sha1-4BMsZ3sbncgwBFEW0Yrbf2kk8XU=", "dev": true, "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" + "async": "^1.4.0", + "debug": "^2.1.1", + "minimist": "^1.1.1", + "mkdirp": "^0.5.1", + "untildify": "^1.0.0" }, "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true - } - } - }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true - }, - "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, - "node-releases": { - "version": "1.1.61", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", - "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "untildify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz", + "integrity": "sha1-TYAx0YBvT718QrAjeq8hNoYmJjU=", + "dev": true, + "requires": { + "user-home": "^1.0.0" + } + } } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "mongodb-download-url": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-0.5.2.tgz", + "integrity": "sha512-hEwWEsJUh/XbY8yy7EfwF4a6Hres/v89EyMV5/l3dWh8zT2isIo9gt94RkLgvdgOliBw4jtGbViIOcvM6F1G/w==", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "async": "^2.1.2", + "debug": "^2.2.0", + "lodash.defaults": "^4.0.0", + "minimist": "^1.2.0", + "mongodb-version-list": "^1.0.0", + "request": "^2.65.0", + "semver": "^5.0.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "mongodb-runner": { + "version": "github:mongodb-js/runner#dfb9a520147de6e2537f7c1c21a5e7005d1905f8", + "from": "github:mongodb-js/runner", "dev": true, "requires": { - "once": "^1.3.2" + "async": "^3.1.0", + "clui": "^0.3.6", + "debug": "^4.1.1", + "fs-extra": "^8.1.0", + "is-mongodb-running": "^1.0.1", + "lodash.defaults": "^4.2.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "mongodb": "^3.4.0", + "mongodb-dbpath": "^0.0.1", + "mongodb-tools": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", + "mongodb-version-manager": "^1.4.3", + "untildify": "^4.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "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" + } + } } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "mongodb-tools": { + "version": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", + "from": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", "dev": true, "requires": { - "path-key": "^2.0.0" + "debug": "^2.2.0", + "lodash": "^4.17.12", + "mkdirp": "0.5.0", + "mongodb-core": "*", + "rimraf": "2.2.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "rimraf": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=", + "dev": true + } } }, - "npmlog": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz", - "integrity": "sha1-0DlQ4OeM4VJ7om0qdZLpNIrD518=", + "mongodb-version-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mongodb-version-list/-/mongodb-version-list-1.0.0.tgz", + "integrity": "sha1-8lAxz83W8UWx3o/OKk6+wCiLtKQ=", "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" + "cheerio": "^0.22.0", + "debug": "^2.2.0", + "downcache": "^0.0.9", + "fs-extra": "^1.0.0", + "minimist": "^1.1.1", + "semver": "^5.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "mongodb-version-manager": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.4.3.tgz", + "integrity": "sha512-+zQdWHLdumqX4mNyqLP08LIa8Wsn52AyU8lEBRx4onlCN13AVNCvgHtCjBAquCYC/wm1rT1i7nAglSJq1LD81Q==", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "ampersand-state": "^5.0.3", + "async": "^2.1.2", + "chalk": "^2.1.0", + "debug": ">= 2.6.9 < 3.0.0 || >= ^3.1.0", + "docopt": "^0.6.2", + "download": "^6.2.5", + "figures": "^2.0.0", + "fs-extra": "^4.0.2", + "get-mongodb-version": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.1.1", + "mongodb-download-url": "^0.5.2", + "mongodb-version-list": "^1.0.0", + "semver": "^5.3.0", + "tildify": "^1.2.0", + "untildify": "^3.0.2" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "ms": "^2.1.1" } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "escape-string-regexp": "^1.0.5" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true } } }, - "object-hash": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", - "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==", - "dev": true - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "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 }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + }, + "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 + } + } + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-netstat": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-netstat/-/node-netstat-1.8.0.tgz", + "integrity": "sha512-P1a5Sh9FfjTXxI6hC9q/Nqre8kT63FQxBCr1qz5ffk76EkQBH62+XEhIhlzfz6Bz+FRwOFqidW2FDGXnOXvyJQ==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "node-releases": { + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", + "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==", + "dev": true + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, "object-path": { @@ -10263,6 +10959,12 @@ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -10278,8 +10980,14 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "p-each-series": { - "version": "1.0.0", + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, @@ -10287,6 +10995,15 @@ "p-reduce": "^1.0.0" } }, + "p-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", + "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=", + "dev": true, + "requires": { + "p-timeout": "^1.1.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -10317,6 +11034,15 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -10345,47 +11071,734 @@ "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" + } + } + } + }, + "@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": { + "@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": { + "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" + } + } + } + }, + "@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-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==", + "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": { - "agent-base": "4", - "debug": "3.1.0" + "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": "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": "6", + "debug": "4" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "2.0.0" + "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 } } }, - "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==", + "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": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "@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": "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.1" + "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": { @@ -10396,225 +11809,145 @@ } } }, - "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==", + "ldapjs": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.2.2.tgz", + "integrity": "sha512-PgMVYKWUjkkK6v81QQc+kKsr4TcKRggYuvjwo1h4ZEhaXGIkhLvcK9Y60nZqR5RRvyYbt8Ott1VyN7S5EiYArA==", "dev": true, "requires": { - "regenerator-runtime": "^0.13.4" + "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" } }, - "@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==", + "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": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" + "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" } }, - "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=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "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=", + "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": { - "is-extglob": "^1.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.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.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==", + }, + "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": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "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 + } + } + }, + "pg": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", + "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "dev": true, + "requires": { + "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" + } + }, + "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 + }, + "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": { + "assert-options": "0.6.2", + "pg": "8.5.1", + "pg-minify": "1.6.1", + "spex": "3.0.2" + } + }, + "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 +11956,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 } } @@ -10762,6 +12107,15 @@ "pify": "^3.0.0" } }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -10775,36 +12129,18 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "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 +12159,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", @@ -10977,6 +12289,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -11063,6 +12381,12 @@ "react-is": "^16.8.1" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -11162,6 +12486,24 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "ps-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", + "integrity": "sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=", + "dev": true, + "requires": { + "table-parser": "^0.1.3" + } + }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -11865,6 +13207,23 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dev": true, + "requires": { + "commander": "^2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -12248,6 +13607,24 @@ } } }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "requires": { + "sort-keys": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -12398,6 +13775,121 @@ "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", "dev": true }, + "start-server-and-test": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.11.6.tgz", + "integrity": "sha512-+0T83W/R7CVgIE2HJcrpJDleLt7Skc2Xj8jWWsItRGdpZwenAv0YtIpBEKoL64pwUtPAPoHuYUtvWUOfCRoVjg==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.3.1", + "execa": "3.4.0", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "5.2.0" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "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", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "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" + } + }, + "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 + }, + "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" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "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 + }, + "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" + } + } + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -12441,6 +13933,15 @@ "readable-stream": "^2.0.2" } }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", @@ -12726,18 +14227,42 @@ } } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "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", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", @@ -12860,12 +14385,48 @@ } } }, + "table-parser": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", + "integrity": "sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=", + "dev": true, + "requires": { + "connected-domain": "^1.0.0" + } + }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + } + } + }, "teeny-request": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", @@ -12941,12 +14502,27 @@ "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, "timers-browserify": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", @@ -12956,6 +14532,16 @@ "process": "~0.11.0" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12981,6 +14567,12 @@ "is-negated-glob": "^1.0.0" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -13079,6 +14671,15 @@ } } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -13194,6 +14795,16 @@ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", "dev": true }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -13301,6 +14912,12 @@ "through2-filter": "^3.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -13347,6 +14964,12 @@ } } }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, "upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -13394,6 +15017,21 @@ } } }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, "urlgrey": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", @@ -13406,6 +15044,12 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -13678,6 +15322,19 @@ "browser-process-hrtime": "^1.0.0" } }, + "wait-on": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.2.0.tgz", + "integrity": "sha512-U1D9PBgGw2XFc6iZqn45VBubw02VsLwnZWteQ1au4hUVHasTZuFSKRzlTB2dqgLhji16YVI8fgpEpwUdCr8B6g==", + "dev": true, + "requires": { + "axios": "^0.19.2", + "joi": "^17.1.1", + "lodash": "^4.17.19", + "minimist": "^1.2.5", + "rxjs": "^6.5.5" + } + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -14173,6 +15830,16 @@ "object.assign": "^4.1.0" } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", diff --git a/package.json b/package.json index f3d3036a6..5a096a316 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,10 @@ "jsdoc": "3.6.3", "jsdoc-babel": "0.5.0", "metro-react-native-babel-preset": "0.59.0", + "mongodb-runner": "mongodb-js/runner", "parse-server": "github:parse-community/parse-server#master", "regenerator-runtime": "0.13.5", + "start-server-and-test": "^1.11.6", "vinyl-source-stream": "2.0.0" }, "optionalDependencies": { @@ -88,7 +90,9 @@ "watch:browser": "cross-env PARSE_BUILD=browser npm run watch", "watch:node": "cross-env PARSE_BUILD=node npm run watch", "watch:react-native": "cross-env PARSE_BUILD=react-native npm run watch", - "integration": "cross-env TESTING=1 jasmine --config=jasmine.json", + "integration": " cross-env TESTING=1 jasmine --config=jasmine.json", + "preintegration": "mongodb-runner start", + "postintegration": "mongodb-runner stop", "docs": "jsdoc -c ./jsdoc-conf.json ./src", "prepare": "npm run build", "release_docs": "./release_docs.sh", diff --git a/src/ParseUser.js b/src/ParseUser.js index 115eeff1b..a7b81dfcb 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -1,3 +1,4 @@ +/* eslint-disable indent */ /** * Copyright (c) 2015-present, Parse, LLC. * All rights reserved. @@ -45,9 +46,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 +69,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.upgradeToRevocableSession( - this, - upgradeOptions - ); + return controller.upgradeToRevocableSession(this, upgradeOptions); } /** @@ -89,7 +87,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 +121,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 +152,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 +392,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 +420,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.signUp( - this, - attrs, - signupOptions - ); + return controller.signUp(this, attrs, signupOptions); } /** @@ -545,7 +542,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 +550,7 @@ class ParseUser extends ParseObject { value: protoProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -566,7 +563,7 @@ class ParseUser extends ParseObject { value: classProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -632,31 +629,74 @@ class ParseUser extends ParseObject { * saves the session to disk, so you can retrieve the currently logged in * user using current. * - * @param {string} username The username (or email) to log in with. - * @param {string} password The password to log in with. + * @param {string | object} usernameOrObject The username (or email) to log in with or an object with auth fields. + * @param {string | object} passwordOrOptions The password to log in with or options if usernameOrObject is an object. * @param {object} options * @static * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - 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.' - ) - ); - } else if (typeof password !== 'string') { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Password must be a string.' + static logIn( + usernameOrObject: string | Object, + passwordOrOptions: string | FullOptions, + options?: FullOptions + ) { + const usernameIsObject = typeof usernameOrObject === 'object'; + if (typeof usernameOrObject !== 'string') { + if (!usernameIsObject) { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Username must be a string or an object with username and password keys.' + ) + ); + } + if (typeof usernameOrObject.username !== 'string') { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Auth payload should contain username key with string value' + ) + ); + } + if (typeof usernameOrObject.password !== 'string') { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Auth payload should contain password key with string value' + ) + ); + } + if (usernameOrObject.authData && typeof usernameOrObject.authData !== 'object') { + return Promise.reject( + new ParseError(ParseError.OTHER_CAUSE, 'authData should be an object') + ); + } + if ( + Object.keys(usernameOrObject).some( + key => !['authData', 'username', 'password'].includes(key) ) - ); + ) { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'This operation only support authData, username and password keys' + ) + ); + } + } + if (typeof passwordOrOptions !== 'string' && !usernameIsObject) { + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } const user = new this(); - user._finishFetch({ username: username, password: password }); + user._finishFetch( + usernameIsObject + ? usernameOrObject + : { + username: usernameOrObject, + password: passwordOrOptions, + } + ); return user.logIn(options); } @@ -673,14 +713,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 +740,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 +774,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 +818,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.requestPasswordReset( - email, requestOptions - ); + return controller.requestPasswordReset(email, requestOptions); } /** @@ -814,21 +854,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 +948,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 +990,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 +1007,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 +1027,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 +1063,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 +1106,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 +1131,29 @@ const DefaultController = { const stateController = CoreManager.getObjectStateController(); const auth = { username: user.get('username'), - password: user.get('password') + password: user.get('password'), + authData: user.get('authData'), }; - 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 +1172,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 +1182,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 +1213,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 +1249,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/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index fce28b737..08ac8e8cf 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() { 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,113 @@ 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.'); + ParseUser.logIn(undefined, 'password') + .then(null, err => { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe( + 'Username must be a string or an object with username and password keys.' + ); + + return ParseUser.logIn('username', undefined); + }) + .then(null, err => { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('Password must be a string.'); + + done(); + }); + }); - return ParseUser.logIn('username', {}); - }).then(null, (err) => { + it('fail login when invalid object passed via username', async () => { + ParseUser.enableUnsafeCurrentUser(); + ParseUser._clearCache(); + try { + await ParseUser.logIn({}, 'password'); + expect(false).toBeTrue(); + } catch (err) { expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe('Password must be a string.'); + expect(err.message).toBe('Auth payload should contain username key with string value'); + } + try { + await ParseUser.logIn({ username: 'test' }, {}); + expect(false).toBeTrue(); + } catch (err) { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('Auth payload should contain password key with string value'); + } + try { + await ParseUser.logIn({ username: 'test', password: 'test', authData: 'test' }, {}); + expect(false).toBeTrue(); + } catch (err) { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('authData should be an object'); + } + try { + await ParseUser.logIn( + { + username: 'test', + password: 'test', + authData: { test: true }, + aField: true, + }, + {} + ); + expect(false).toBeTrue(); + } catch (err) { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('This operation only support authData, username and password keys'); + } + }); - done(); + it('should login with username as object', async () => { + ParseUser.enableUnsafeCurrentUser(); + ParseUser._clearCache(); + CoreManager.setRESTController({ + request(method, path, body) { + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); + expect(body.authData).toEqual({ test: { data: true } }); + + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + authDataResponse: { + test: { challenge: 'test' }, + }, + }, + 200 + ); + }, + ajax() {}, + }); + const u = await ParseUser.logIn({ + username: 'username', + password: 'password', + authData: { test: { data: true } }, + }); + expect(u.id).toBe('uid2'); + expect(u.getSessionToken()).toBe('123abc'); + expect(u.isCurrent()).toBe(true); + expect(u.authenticated()).toBe(true); + expect(ParseUser.current()).toBe(u); + ParseUser._clearCache(); + const current = ParseUser.current(); + expect(current instanceof ParseUser).toBe(true); + expect(current.id).toBe('uid2'); + expect(current.authenticated()).toBe(true); + expect(current.get('authDataResponse')).toEqual({ + test: { challenge: 'test' }, }); }); - it('preserves changes when logging in', (done) => { + it('preserves changes when logging in', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -327,17 +435,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 +459,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 +468,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 +499,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 +525,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 +580,7 @@ describe('ParseUser', () => { return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); ParseUser.requestPasswordReset('me@parse.com'); @@ -475,122 +593,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 +744,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 +775,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 +907,12 @@ describe('ParseUser', () => { Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + }, + 200 + ); }, ajax() {}, }); @@ -760,10 +925,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 +953,12 @@ describe('ParseUser', () => { Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + }, + 200 + ); }, ajax() {}, }); @@ -801,10 +972,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 +990,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 +1036,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 +1063,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 +1089,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 +1119,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 +1137,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 +1159,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 +1179,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 +1216,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 +1231,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 +1252,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 +1283,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 +1328,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 +1357,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 +1381,7 @@ describe('ParseUser', () => { getAuthType() { return 'test'; }, - deauthenticate() {} + deauthenticate() {}, }; const user = new ParseUser(); @@ -1177,7 +1389,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 +1397,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 +1464,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 +1507,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 +1536,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 +1562,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 +1617,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 +1668,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 +1698,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 +1724,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 +1741,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 +1755,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 +1783,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 +1823,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 +1852,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 +1872,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(); From 155214319c281d248f937be5a233b3e37d9399cf Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 12:33:55 +0100 Subject: [PATCH 02/11] Add prettier --- integration/cloud/main.js | 36 +- integration/server.js | 40 +- integration/test/ArrayOperationsTest.js | 767 ++-- integration/test/CustomAuth.js | 2 +- integration/test/DirtyTest.js | 371 +- integration/test/IdempotencyTest.js | 70 +- integration/test/IncrementTest.js | 397 +- integration/test/ParseACLTest.js | 269 +- integration/test/ParseCloudTest.js | 194 +- integration/test/ParseConfigTest.js | 40 +- integration/test/ParseFileTest.js | 96 +- integration/test/ParseGeoBoxTest.js | 160 +- integration/test/ParseGeoPointTest.js | 506 ++- integration/test/ParseLiveQueryTest.js | 186 +- integration/test/ParseLocalDatastoreTest.js | 1646 ++++--- integration/test/ParseMasterKeyTest.js | 50 +- integration/test/ParseObjectTest.js | 2516 ++++++----- integration/test/ParsePolygonTest.js | 219 +- integration/test/ParseQueryAggregateTest.js | 138 +- integration/test/ParseQueryTest.js | 2958 +++++++------ integration/test/ParseRelationTest.js | 383 +- integration/test/ParseRoleTest.js | 16 +- integration/test/ParseSchemaTest.js | 622 +-- integration/test/ParseSubclassTest.js | 230 +- integration/test/ParseUserTest.js | 1059 ++--- integration/test/clear.js | 6 +- integration/test/helper.js | 10 +- integration/test/mockLocalStorage.js | 1 - integration/test/sleep.js | 4 +- package-lock.json | 2887 ++++++++----- package.json | 15 + src/Analytics.js | 21 +- src/AnonymousUtils.js | 22 +- src/Cloud.js | 68 +- src/CloudCode.js | 1 - src/CoreManager.js | 556 ++- src/CryptoController.js | 8 +- src/EventEmitter.js | 6 +- src/FacebookUtils.js | 94 +- src/InstallationController.js | 10 +- src/LiveQueryClient.js | 173 +- src/LiveQuerySubscription.js | 18 +- src/LocalDatastore.js | 67 +- src/LocalDatastoreController.js | 10 +- src/LocalDatastoreController.react-native.js | 12 +- src/LocalDatastoreUtils.js | 20 +- src/ObjectStateMutations.js | 63 +- src/OfflineQuery.js | 221 +- src/Parse.js | 170 +- src/ParseACL.js | 84 +- src/ParseConfig.js | 111 +- src/ParseError.js | 8 +- src/ParseFile.js | 326 +- src/ParseGeoPoint.js | 45 +- src/ParseHooks.js | 67 +- src/ParseInstallation.js | 12 +- src/ParseLiveQuery.js | 46 +- src/ParseObject.js | 809 ++-- src/ParseOp.js | 149 +- src/ParsePolygon.js | 52 +- src/ParseQuery.js | 698 +-- src/ParseRelation.js | 36 +- src/ParseRole.js | 42 +- src/ParseSchema.js | 132 +- src/ParseSession.js | 60 +- src/ParseUser.js | 413 +- src/Push.js | 33 +- src/RESTController.js | 257 +- src/SingleInstanceStateController.js | 56 +- src/Socket.weapp.js | 12 +- src/Storage.js | 40 +- src/StorageController.browser.js | 2 +- src/StorageController.default.js | 2 +- src/StorageController.react-native.js | 16 +- src/StorageController.weapp.js | 2 +- src/TaskQueue.js | 42 +- src/UniqueInstanceStateController.js | 40 +- src/Xhr.weapp.js | 20 +- src/__tests__/Analytics-test.js | 97 +- src/__tests__/AnonymousUtils-test.js | 52 +- src/__tests__/Cloud-test.js | 343 +- src/__tests__/CoreManager-test.js | 480 ++- src/__tests__/FacebookUtils-test.js | 198 +- src/__tests__/Hooks-test.js | 424 +- src/__tests__/InstallationController-test.js | 72 +- src/__tests__/LiveQueryClient-test.js | 831 ++-- src/__tests__/LocalDatastore-test.js | 595 +-- src/__tests__/ObjectStateMutations-test.js | 220 +- src/__tests__/OfflineQuery-test.js | 878 ++-- src/__tests__/Parse-test.js | 200 +- src/__tests__/ParseACL-test.js | 242 +- src/__tests__/ParseConfig-test.js | 269 +- src/__tests__/ParseError-test.js | 22 +- src/__tests__/ParseFile-test.js | 847 ++-- src/__tests__/ParseGeoPoint-test.js | 42 +- src/__tests__/ParseInstallation-test.js | 34 +- src/__tests__/ParseLiveQuery-test.js | 211 +- src/__tests__/ParseObject-test.js | 3794 +++++++++-------- src/__tests__/ParseOp-test.js | 422 +- src/__tests__/ParsePolygon-test.js | 66 +- src/__tests__/ParseQuery-test.js | 3485 +++++++-------- src/__tests__/ParseRelation-test.js | 290 +- src/__tests__/ParseRole-test.js | 115 +- src/__tests__/ParseSchema-test.js | 349 +- src/__tests__/ParseSession-test.js | 164 +- src/__tests__/ParseUser-test.js | 1781 ++++---- src/__tests__/Push-test.js | 93 +- src/__tests__/RESTController-test.js | 792 ++-- .../SingleInstanceStateController-test.js | 751 +++- src/__tests__/Storage-test.js | 347 +- src/__tests__/TaskQueue-test.js | 76 +- .../UniqueInstanceStateController-test.js | 260 +- src/__tests__/arrayContainsObject-test.js | 42 +- src/__tests__/browser-test.js | 96 +- src/__tests__/canBeSerialized-test.js | 106 +- src/__tests__/decode-test.js | 129 +- src/__tests__/encode-test.js | 182 +- src/__tests__/equals-test.js | 90 +- src/__tests__/escape-test.js | 23 +- src/__tests__/parseDate-test.js | 16 +- src/__tests__/promiseUtils-test.js | 10 +- src/__tests__/react-native-test.js | 88 +- src/__tests__/unique-test.js | 69 +- src/__tests__/unsavedChildren-test.js | 162 +- src/__tests__/weapp-test.js | 78 +- src/arrayContainsObject.js | 5 +- src/canBeSerialized.js | 8 +- src/decode.js | 34 +- src/encode.js | 75 +- src/equals.js | 31 +- src/escape.js | 14 +- src/interfaces/react-native.js | 16 +- src/isRevocableSession.js | 2 +- src/parseDate.js | 9 +- src/promiseUtils.js | 25 +- src/unique.js | 4 +- src/unsavedChildren.js | 41 +- 137 files changed, 22889 insertions(+), 18354 deletions(-) diff --git a/integration/cloud/main.js b/integration/cloud/main.js index 6b632de2f..c193689db 100644 --- a/integration/cloud/main.js +++ b/integration/cloud/main.js @@ -1,51 +1,51 @@ /* global Parse */ -Parse.Cloud.define("bar", function(request) { +Parse.Cloud.define("bar", function (request) { if (request.params.key2 === "value1") { - return 'Foo'; + return "Foo"; } else { throw "bad stuff happened"; } }); -Parse.Cloud.define('TestFetchFromLocalDatastore', function (request) { - const object = new Parse.Object('Item'); +Parse.Cloud.define("TestFetchFromLocalDatastore", function (request) { + const object = new Parse.Object("Item"); object.id = request.params.id; - object.set('foo', 'changed'); + object.set("foo", "changed"); return object.save(); }); -Parse.Cloud.define('UpdateUser', function (request) { +Parse.Cloud.define("UpdateUser", function (request) { const user = new Parse.User(); user.id = request.params.id; - user.set('foo', 'changed'); + user.set("foo", "changed"); return user.save(null, { useMasterKey: true }); }); -Parse.Cloud.define('CloudFunctionIdempotency', function () { - const object = new Parse.Object('IdempotencyItem'); +Parse.Cloud.define("CloudFunctionIdempotency", function () { + const object = new Parse.Object("IdempotencyItem"); 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() { +Parse.Cloud.job("CloudJob2", function () { return new Promise((resolve) => { - setTimeout(function() { + setTimeout(function () { resolve({ - status: 'cloud job completed' - }) + status: "cloud job completed", + }); }, 1000); }); }); -Parse.Cloud.job('CloudJobFailing', function() { - throw 'cloud job failed'; +Parse.Cloud.job("CloudJobFailing", function () { + throw "cloud job failed"; }); diff --git a/integration/server.js b/integration/server.js index 35f021190..4d2801e93 100644 --- a/integration/server.js +++ b/integration/server.js @@ -1,26 +1,26 @@ -const express = require('express'); -const ParseServer = require('parse-server').ParseServer; +const express = require("express"); +const ParseServer = require("parse-server").ParseServer; const app = express(); -const CustomAuth = require('./test/CustomAuth'); +const CustomAuth = require("./test/CustomAuth"); const api = new ParseServer({ - databaseURI: 'mongodb://localhost:27017/integration', - appId: 'integration', - masterKey: 'notsosecret', - serverURL: 'http://localhost:1337/parse', + databaseURI: "mongodb://localhost:27017/integration", + appId: "integration", + masterKey: "notsosecret", + serverURL: "http://localhost:1337/parse", cloud: `${__dirname}/cloud/main.js`, liveQuery: { - classNames: ['TestObject', 'DiffObject'], + classNames: ["TestObject", "DiffObject"], }, startLiveQueryServer: true, auth: { myAuth: { module: CustomAuth, - option1: 'hello', - option2: 'world', + option1: "hello", + option2: "world", }, facebook: { - appIds: "test" + appIds: "test", }, twitter: { consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", @@ -31,28 +31,28 @@ const api = new ParseServer({ silent: true, idempotencyOptions: { paths: [ - 'functions/CloudFunctionIdempotency', - 'jobs/CloudJob1', - 'classes/IdempotentTest' + "functions/CloudFunctionIdempotency", + "jobs/CloudJob1", + "classes/IdempotentTest", ], - ttl: 120 + ttl: 120, }, serverStartComplete: () => { /* Ignore ParseError: schema class name does not revalidate */ }, }); -app.use('/parse', api); +app.use("/parse", api); -const TestUtils = require('parse-server').TestUtils; +const TestUtils = require("parse-server").TestUtils; -app.get('/clear/:fast', (req, res) => { +app.get("/clear/:fast", (req, res) => { const { fast } = req.params; TestUtils.destroyAllDataPermanently(fast).then(() => { - res.send('{}'); + res.send("{}"); }); }); module.exports = { - app + app, }; diff --git a/integration/test/ArrayOperationsTest.js b/integration/test/ArrayOperationsTest.js index 95cb8a86c..803f66aa9 100644 --- a/integration/test/ArrayOperationsTest.js +++ b/integration/test/ArrayOperationsTest.js @@ -1,393 +1,476 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -describe('Array Operations', () => { +describe("Array Operations", () => { beforeAll((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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) => { - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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.addUnique('numbers', number); + 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.addUnique("numbers", number); }); - assert.equal(object.get('numbers').length, 7); + assert.equal(object.get("numbers").length, 7); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - it('removes objects by id', (done) => { - const badEgg = new Parse.Object('Egg'); - badEgg.set('quality', 'rotten'); - const goodEgg = new Parse.Object('Egg'); - goodEgg.set('quality', 'good'); - const ostrichEgg = new Parse.Object('Egg'); - ostrichEgg.set('quality', 'huge'); + it("removes objects by id", (done) => { + const badEgg = new Parse.Object("Egg"); + badEgg.set("quality", "rotten"); + const goodEgg = new Parse.Object("Egg"); + goodEgg.set("quality", "good"); + const ostrichEgg = new Parse.Object("Egg"); + 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(); - }); + 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(); + }); }); }); 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..ca06d9563 100644 --- a/integration/test/DirtyTest.js +++ b/integration/test/DirtyTest.js @@ -1,208 +1,249 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); -const Parent = Parse.Object.extend('Parent'); -const Child = Parse.Object.extend('Child'); +const TestObject = Parse.Object.extend("TestObject"); +const Parent = Parse.Object.extend("Parent"); +const Child = Parse.Object.extend("Child"); -describe('Dirty Objects', () => { +describe("Dirty Objects", () => { beforeEach((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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.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); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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); + 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(); - }); + 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(); + }); }); - 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..f2cd99629 100644 --- a/integration/test/IdempotencyTest.js +++ b/integration/test/IdempotencyTest.js @@ -1,9 +1,9 @@ -'use strict'; +"use strict"; -const clear = require('./clear'); -const Parse = require('../../node'); +const clear = require("./clear"); +const Parse = require("../../node"); -const Item = Parse.Object.extend('IdempotencyItem'); +const Item = Parse.Object.extend("IdempotencyItem"); const RESTController = Parse.CoreManager.getRESTController(); const XHR = RESTController._getXHR(); @@ -12,18 +12,18 @@ function DuplicateXHR(requestId) { const xhr = new XHR(); const send = xhr.send; xhr.send = function () { - this.setRequestHeader('X-Parse-Request-Id', requestId); + this.setRequestHeader("X-Parse-Request-Id", requestId); send.apply(this, arguments); - } + }; return xhr; } return XHRWrapper; } -describe('Idempotency', () => { +describe("Idempotency", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); RESTController._setXHR(XHR); clear().then(() => { @@ -31,42 +31,52 @@ 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'); + 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"); const query = new Parse.Query(Item); const results = await query.find(); expect(results.length).toBe(1); }); - it('handle duplicate job request', async () => { - 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'); + it("handle duplicate job request", async () => { + 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"); const jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - expect(jobStatus.get('status')).toBe('succeeded'); - expect(jobStatus.get('params').startedBy).toBe('Monty Python'); + expect(jobStatus.get("status")).toBe("succeeded"); + expect(jobStatus.get("params").startedBy).toBe("Monty Python"); }); - it('handle duplicate POST / PUT request', async () => { - RESTController._setXHR(DuplicateXHR('1234')); - const testObject = new Parse.Object('IdempotentTest'); + it("handle duplicate POST / PUT request", async () => { + RESTController._setXHR(DuplicateXHR("1234")); + const testObject = new Parse.Object("IdempotentTest"); await testObject.save(); - await expectAsync(testObject.save()).toBeRejectedWithError('Duplicate request'); + await expectAsync(testObject.save()).toBeRejectedWithError( + "Duplicate request" + ); - RESTController._setXHR(DuplicateXHR('5678')); - testObject.set('foo', 'bar'); + RESTController._setXHR(DuplicateXHR("5678")); + testObject.set("foo", "bar"); await testObject.save(); - await expectAsync(testObject.save()).toBeRejectedWithError('Duplicate request'); + await expectAsync(testObject.save()).toBeRejectedWithError( + "Duplicate request" + ); - const query = new Parse.Query('IdempotentTest'); + const query = new Parse.Query("IdempotentTest"); const results = await query.find(); expect(results.length).toBe(1); - expect(results[0].get('foo')).toBe('bar'); + expect(results[0].get("foo")).toBe("bar"); }); }); diff --git a/integration/test/IncrementTest.js b/integration/test/IncrementTest.js index cd0e4f51e..c3cc5b1ae 100644 --- a/integration/test/IncrementTest.js +++ b/integration/test/IncrementTest.js @@ -1,227 +1,278 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Increment', () => { +describe("Increment", () => { beforeEach((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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.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(); + }); }); - it('can increment on a fresh object', () => { + it("can increment on a fresh object", () => { const object = new TestObject(); - object.set('score', 1); - object.increment('score'); - assert.equal(object.get('score'), 2); + object.set("score", 1); + object.increment("score"); + 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - it('does not increment non-numbers', (done) => { + it("does not increment non-numbers", (done) => { const object = new TestObject(); - object.set('not_score', 'foo'); + object.set("not_score", "foo"); object.save().then(() => { try { - object.increment('not_score'); + object.increment("not_score"); } catch (e) { done(); } }); }); - 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.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(); + }); }); - 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.increment("score"); + 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.increment("numeric"); + 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..0a76005cf 100644 --- a/integration/test/ParseACLTest.js +++ b/integration/test/ParseACLTest.js @@ -1,32 +1,41 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Parse.ACL', () => { +describe("Parse.ACL", () => { beforeEach((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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', () => { + it("acl must be valid", () => { const user = new Parse.User(); assert.equal(user.setACL(`Ceci n'est pas un ACL.`), false); }); - it('can refresh object with acl', async () => { + it("can refresh object with acl", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'alice'); - user.set('password', 'wonderland'); + user.set("username", "alice"); + user.set("password", "wonderland"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -36,11 +45,11 @@ describe('Parse.ACL', () => { assert(o); }); - it('disables public get access', async () => { + it("disables public get access", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'getter'); - user.set('password', 'secret'); + user.set("username", "getter"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -61,11 +70,11 @@ describe('Parse.ACL', () => { } }); - it('disables public find access', async () => { + it("disables public find access", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'finder'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "finder"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -78,16 +87,16 @@ describe('Parse.ACL', () => { assert.equal(object.getACL().getPublicWriteAccess(), false); await Parse.User.logOut(); - const query = new Parse.Query('UniqueObject'); + const query = new Parse.Query("UniqueObject"); const o = await query.find(); assert.equal(o.length, 0); }); - it('disables public update access', async () => { + it("disables public update access", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'updater'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "updater"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -101,7 +110,7 @@ describe('Parse.ACL', () => { await Parse.User.logOut(); - object.set('score', 10); + object.set("score", 10); try { await object.save(); } catch (e) { @@ -109,11 +118,11 @@ describe('Parse.ACL', () => { } }); - it('disables public delete access', async () => { + it("disables public delete access", async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set('username', 'deleter'); - user.set('password', 'secret'); + user.set("username", "deleter"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -134,11 +143,11 @@ describe('Parse.ACL', () => { } }); - it('allows logged in get', async () => { + it("allows logged in get", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'getter2'); - user.set('password', 'secret'); + user.set("username", "getter2"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -149,40 +158,40 @@ describe('Parse.ACL', () => { assert(o); }); - it('allows logged in find', async () => { + it("allows logged in find", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'finder2'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "finder2"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); await object.save(); - const o = await new Parse.Query('UniqueObject').find(); + const o = await new Parse.Query("UniqueObject").find(); assert(o.length > 0); }); - it('allows logged in update', async () => { + it("allows logged in update", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'updater2'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "updater2"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); await object.save(); - object.set('score', 10); + object.set("score", 10); await object.save(); - assert.equal(object.get('score'), 10); + assert.equal(object.get("score"), 10); }); - it('allows logged in delete', async () => { + it("allows logged in delete", async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set('username', 'deleter2'); - user.set('password', 'secret'); + user.set("username", "deleter2"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); @@ -192,11 +201,11 @@ describe('Parse.ACL', () => { await object.destroy(); }); - it('enables get with public read', async () => { + it("enables get with public read", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'getter3'); - user.set('password', 'secret'); + user.set("username", "getter3"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -210,11 +219,11 @@ describe('Parse.ACL', () => { assert(o); }); - it('enables find with public read', async () => { + it("enables find with public read", async () => { const user = new Parse.User(); - const object = new Parse.Object('AlsoUniqueObject'); - user.set('username', 'finder3'); - user.set('password', 'secret'); + const object = new Parse.Object("AlsoUniqueObject"); + user.set("username", "finder3"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -224,16 +233,16 @@ describe('Parse.ACL', () => { await object.save(); Parse.User.logOut(); - const o = await new Parse.Query('AlsoUniqueObject').find(); + const o = await new Parse.Query("AlsoUniqueObject").find(); assert(o.length > 0); }); - it('does not enable update with public read', async () => { + it("does not enable update with public read", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'updater3'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "updater3"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -243,7 +252,7 @@ describe('Parse.ACL', () => { await object.save(); Parse.User.logOut(); - object.set('score', 10); + object.set("score", 10); try { await object.save(); } catch (e) { @@ -251,11 +260,11 @@ describe('Parse.ACL', () => { } }); - it('does not enable delete with public read', async () => { + it("does not enable delete with public read", async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set('username', 'deleter3'); - user.set('password', 'secret'); + user.set("username", "deleter3"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -272,11 +281,11 @@ describe('Parse.ACL', () => { } }); - it('does not enable get with public write', async () => { + it("does not enable get with public write", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'getter4'); - user.set('password', 'secret'); + user.set("username", "getter4"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -293,11 +302,11 @@ describe('Parse.ACL', () => { } }); - it('does not enable find with public write', async () => { + it("does not enable find with public write", async () => { const user = new Parse.User(); - const object = new Parse.Object('AnotherUniqueObject'); - user.set('username', 'finder4'); - user.set('password', 'secret'); + const object = new Parse.Object("AnotherUniqueObject"); + user.set("username", "finder4"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -307,15 +316,15 @@ describe('Parse.ACL', () => { await object.save(); await Parse.User.logOut(); - const o = await new Parse.Query('AnotherUniqueObject').find(); + const o = await new Parse.Query("AnotherUniqueObject").find(); assert.equal(o.length, 0); }); - it('enables update with public read', async () => { + it("enables update with public read", async () => { const user = new Parse.User(); - const object = new Parse.Object('UniqueObject'); - user.set('username', 'updater4'); - user.set('password', 'secret'); + const object = new Parse.Object("UniqueObject"); + user.set("username", "updater4"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -325,15 +334,15 @@ describe('Parse.ACL', () => { await object.save(); await Parse.User.logOut(); - object.set('score', 10); + object.set("score", 10); await object.save(); }); - it('enables delete with public read', async () => { + it("enables delete with public read", async () => { const user = new Parse.User(); const object = new TestObject(); - user.set('username', 'deleter4'); - user.set('password', 'secret'); + user.set("username", "deleter4"); + user.set("password", "secret"); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -346,12 +355,12 @@ describe('Parse.ACL', () => { await object.destroy(); }); - it('can grant get access to another user', async () => { + it("can grant get access to another user", async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('aaa', 'password'); + const user1 = await Parse.User.signUp("aaa", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('bbb', 'password'); + const user2 = await Parse.User.signUp("bbb", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -359,19 +368,19 @@ describe('Parse.ACL', () => { object.setACL(acl); await object.save(); - await Parse.User.logIn('aaa', 'password'); + await Parse.User.logIn("aaa", "password"); const query = new Parse.Query(TestObject); const o = await query.get(object.id); assert.equal(o.id, object.id); }); - it('can grant find access to another user', async () => { - const object = new Parse.Object('ThatOneObject'); - const user1 = await Parse.User.signUp('ccc', 'password'); + it("can grant find access to another user", async () => { + const object = new Parse.Object("ThatOneObject"); + const user1 = await Parse.User.signUp("ccc", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('ddd', 'password'); + const user2 = await Parse.User.signUp("ddd", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -379,20 +388,20 @@ describe('Parse.ACL', () => { object.setACL(acl); await object.save(); - await Parse.User.logIn('ccc', 'password'); + await Parse.User.logIn("ccc", "password"); - const query = new Parse.Query('ThatOneObject'); + const query = new Parse.Query("ThatOneObject"); const o = await query.find(); assert(o.length > 0); }); - it('can grant update access to another user', async () => { + it("can grant update access to another user", async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('eee', 'password'); + const user1 = await Parse.User.signUp("eee", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('fff', 'password'); + const user2 = await Parse.User.signUp("fff", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -400,19 +409,19 @@ describe('Parse.ACL', () => { object.setACL(acl); await object.save(); - await Parse.User.logIn('eee', 'password'); + await Parse.User.logIn("eee", "password"); - object.set('score', 10); + object.set("score", 10); const o = await object.save(); - assert.equal(o.get('score'), 10); + assert.equal(o.get("score"), 10); }); - it('can grant delete access to another user', async () => { + 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'); + const user2 = await Parse.User.signUp("hhh", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -420,16 +429,16 @@ describe('Parse.ACL', () => { object.setACL(acl); await object.save(); - await Parse.User.logIn('ggg', 'password'); + await Parse.User.logIn("ggg", "password"); await object.destroy(); }); - it('does not grant public get access with another user acl', async () => { + it("does not grant public get access with another user acl", async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('iii', 'password'); + const user1 = await Parse.User.signUp("iii", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('jjj', 'password'); + const user2 = await Parse.User.signUp("jjj", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -447,12 +456,12 @@ describe('Parse.ACL', () => { } }); - it('does not grant public find access with another user acl', async () => { - const object = new Parse.Object('ThatOneObject'); - const user1 = await Parse.User.signUp('kkk', 'password'); + it("does not grant public find access with another user acl", async () => { + const object = new Parse.Object("ThatOneObject"); + const user1 = await Parse.User.signUp("kkk", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('lll', 'password'); + const user2 = await Parse.User.signUp("lll", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -462,19 +471,19 @@ describe('Parse.ACL', () => { await Parse.User.logOut(); - const query = new Parse.Query('ThatOneObject'); + const query = new Parse.Query("ThatOneObject"); const o = await query.find(); assert.equal(o.length, 0); }); - it('does not grant public update access with another user acl', async () => { + it("does not grant public update access with another user acl", async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('mmm', 'password'); + const user1 = await Parse.User.signUp("mmm", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('nnn', 'password'); + const user2 = await Parse.User.signUp("nnn", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); acl.setReadAccess(user1, true); @@ -483,7 +492,7 @@ describe('Parse.ACL', () => { await Parse.User.logOut(); - object.set('score', 10); + object.set("score", 10); try { await object.save(); } catch (e) { @@ -491,13 +500,13 @@ describe('Parse.ACL', () => { } }); - it('does not grant public destroy access with another user acl', async () => { + it("does not grant public destroy access with another user acl", async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('ooo', 'password'); + const user1 = await Parse.User.signUp("ooo", "password"); await Parse.User.logOut(); - const user2 = await Parse.User.signUp('ppp', 'password'); + const user2 = await Parse.User.signUp("ppp", "password"); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -514,32 +523,32 @@ describe('Parse.ACL', () => { } }); - it('allows access with an empty acl', async () => { - await Parse.User.signUp('tdurden', 'mayhem', { + 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'); - assert.equal(user.get('foo'), 'bar'); + const user = await Parse.User.logIn("tdurden", "mayhem"); + assert.equal(user.get("foo"), "bar"); }); - it('fetches the ACL with included pointers', async () => { - const obj1 = new Parse.Object('TestClass1'); - const obj2 = new Parse.Object('TestClass2'); + it("fetches the ACL with included pointers", async () => { + const obj1 = new Parse.Object("TestClass1"); + const obj2 = new Parse.Object("TestClass2"); const acl = new Parse.ACL(); acl.setPublicReadAccess(true); - obj2.set('ACL', acl); - obj1.set('other', obj2); + obj2.set("ACL", acl); + obj1.set("other", obj2); await obj1.save(); - let query = new Parse.Query('TestClass1'); + let query = new Parse.Query("TestClass1"); const obj1again = await query.first(); assert(obj1again); - assert(!obj1again.get('other').get('ACL')); - query = new Parse.Query('TestClass1'); - query.include('other'); + assert(!obj1again.get("other").get("ACL")); + query = new Parse.Query("TestClass1"); + query.include("other"); const obj1withInclude = await query.first(); - assert(obj1withInclude.get('other').get('ACL')); + assert(obj1withInclude.get("other").get("ACL")); }); }); diff --git a/integration/test/ParseCloudTest.js b/integration/test/ParseCloudTest.js index 01332c8c8..c6248576b 100644 --- a/integration/test/ParseCloudTest.js +++ b/integration/test/ParseCloudTest.js @@ -1,125 +1,151 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); -const sleep = require('./sleep'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); +const sleep = require("./sleep"); -describe('Parse Cloud', () => { +describe("Parse Cloud", () => { beforeAll((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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) => { - const params = { key1: 'value2', key2: 'value1' }; - Parse.Cloud.run('bar', params).then((result) => { - assert.equal('Foo', result); - done(); - }).catch(done.fail); + 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); }); - it('run function with user', (done) => { - const params = { key1: 'value2', key2: 'value1' }; + 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.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); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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) => { - const object = new Parse.Object('TestClass'); + it("run function with object params fail", (done) => { + const object = new Parse.Object("TestClass"); const params = { key1: object }; try { - Parse.Cloud.run('bar', params); + Parse.Cloud.run("bar", params); } catch (e) { - assert.equal(e, 'Error: Parse Objects not allowed here'); + assert.equal(e, "Error: Parse Objects not allowed here"); done(); } }); - 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) => { - 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(); - }); + 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(); + }); }); - it('run long job', async () => { - const jobStatusId = await Parse.Cloud.startJob('CloudJob2'); + it("run long job", async () => { + const jobStatusId = await Parse.Cloud.startJob("CloudJob2"); let jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - assert.equal(jobStatus.get('status'), 'running'); + assert.equal(jobStatus.get("status"), "running"); await sleep(2000); jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - assert.equal(jobStatus.get('status'), 'succeeded'); + 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) => { + it("get jobs data", (done) => { Parse.Cloud.getJobsData().then((result) => { assert.equal(result.in_use.length, 0); assert.equal(result.jobs.length, 3); @@ -127,10 +153,12 @@ describe('Parse Cloud', () => { }); }); - 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..2a59e9e35 100644 --- a/integration/test/ParseConfigTest.js +++ b/integration/test/ParseConfigTest.js @@ -1,8 +1,8 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); function testConfig() { return Parse.Config.save( @@ -11,47 +11,47 @@ function testConfig() { ); } -describe('Parse Config', () => { +describe("Parse Config", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it('can create a config', async () => { + it("can create a config", async () => { const config = await testConfig(); assert.notStrictEqual(config, undefined); - assert.strictEqual(config.get('string'), 's'); - assert.strictEqual(config.get('internal'), 'i'); - assert.strictEqual(config.get('number'), 12); + assert.strictEqual(config.get("string"), "s"); + assert.strictEqual(config.get("internal"), "i"); + assert.strictEqual(config.get("number"), 12); }); - it('can get a config', async () => { + it("can get a config", async () => { await testConfig(); const config = await Parse.Config.get(); assert.notStrictEqual(config, undefined); - assert.strictEqual(config.get('string'), 's'); - assert.strictEqual(config.get('number'), 12); + assert.strictEqual(config.get("string"), "s"); + assert.strictEqual(config.get("number"), 12); }); - it('can get internal config parameter with masterkey', async () => { + it("can get internal config parameter with masterkey", async () => { await testConfig(); const config = await Parse.Config.get({ useMasterKey: true }); - assert.equal(config.get('internal'), 'i'); - assert.equal(config.get('string'), 's'); + assert.equal(config.get("internal"), "i"); + assert.equal(config.get("string"), "s"); }); - it('cannot get internal config parameter without masterkey', async () => { + it("cannot get internal config parameter without masterkey", async () => { await testConfig(); const config = await Parse.Config.get(); - assert.equal(config.get('internal'), undefined); - assert.equal(config.get('string'), 's'); + assert.equal(config.get("internal"), undefined); + assert.equal(config.get("string"), "s"); }); }); diff --git a/integration/test/ParseFileTest.js b/integration/test/ParseFileTest.js index 2bc7daa4d..b6ba6d1aa 100644 --- a/integration/test/ParseFileTest.js +++ b/integration/test/ParseFileTest.js @@ -1,47 +1,49 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -describe('Parse.File', () => { +describe("Parse.File", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); clear().then(done).catch(done.fail); }); - it('can save file with uri', async () => { + 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 file1 = new Parse.File('parse-server-logo', { uri: parseLogo }); + 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(); - const object = new Parse.Object('TestObject'); - object.set('file1', file1); + const object = new Parse.Object("TestObject"); + object.set("file1", file1); await object.save(); - const query = new Parse.Query('TestObject'); + const query = new Parse.Query("TestObject"); let result = await query.get(object.id); - assert.equal(file1.name(), result.get('file1').name()); - assert.equal(file1.url(), result.get('file1').url()); + assert.equal(file1.name(), result.get("file1").name()); + assert.equal(file1.url(), result.get("file1").url()); // Try http - const file2 = new Parse.File('parse-server-logo', { uri: file1.url() }); + const file2 = new Parse.File("parse-server-logo", { uri: file1.url() }); await file2.save(); - object.set('file2', file2); + object.set("file2", file2); await object.save(); result = await query.get(object.id); - assert.equal(file2.url(), result.get('file2').url()); + assert.equal(file2.url(), result.get("file2").url()); }); - 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 file = new Parse.File('parse-server-logo', { uri: parseLogo }); + 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 file = new Parse.File("parse-server-logo", { uri: parseLogo }); file.save().then(() => { assert.equal(file.name(), undefined); assert.equal(file.url(), undefined); @@ -49,52 +51,55 @@ describe('Parse.File', () => { file.cancel(); }); - it('can not get data from unsaved file', async () => { - const file = new Parse.File('parse-server-logo', [61, 170, 236, 120]); + it("can not get data from unsaved file", async () => { + const file = new Parse.File("parse-server-logo", [61, 170, 236, 120]); file._data = null; try { await file.getData(); } catch (e) { - assert.equal(e.message, 'Cannot retrieve data for unsaved ParseFile.'); + assert.equal(e.message, "Cannot retrieve data for unsaved ParseFile."); } }); - it('can get file data from byte array', async () => { - const file = new Parse.File('parse-server-logo', [61, 170, 236, 120]); + it("can get file data from byte array", async () => { + const file = new Parse.File("parse-server-logo", [61, 170, 236, 120]); let data = await file.getData(); - assert.equal(data, 'ParseA=='); + 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=='); + assert.equal(data, "ParseA=="); }); - it('can get file data from base64', async () => { - const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); + it("can get file data from base64", async () => { + const file = new Parse.File("parse-server-logo", { base64: "ParseA==" }); let data = await file.getData(); - assert.equal(data, 'ParseA=='); + 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=='); + 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==' }); + it("can get file data from full base64", async () => { + const file = new Parse.File("parse-server-logo", { + base64: "data:image/jpeg;base64,ParseA==", + }); let data = await file.getData(); - assert.equal(data, 'ParseA=='); + 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=='); + 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 file = new Parse.File('parse-server-logo', { uri: parseLogo }); + it("can delete file", async () => { + 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(); @@ -104,9 +109,10 @@ describe('Parse.File', () => { assert.notEqual(data, deletedData); }); - it('can handle delete file error', async () => { - 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 }); + it("can handle delete file error", async () => { + 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(); assert.equal(false, true); diff --git a/integration/test/ParseGeoBoxTest.js b/integration/test/ParseGeoBoxTest.js index 17bf62f71..9011f070e 100644 --- a/integration/test/ParseGeoBoxTest.js +++ b/integration/test/ParseGeoBoxTest.js @@ -1,16 +1,16 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); const southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398); const northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962); -describe('Geo Box', () => { +describe("Geo Box", () => { beforeAll(() => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); }); @@ -18,94 +18,106 @@ describe('Geo Box', () => { 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); - caltrainStation.set('name', 'caltrain'); + const caltrainStation = new Parse.Object("Location"); + caltrainStation.set("location", caltrainStationLocation); + caltrainStation.set("name", "caltrain"); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object('Location'); - 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); + const santaClara = new Parse.Object("Location"); + 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); }); - 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); - caltrainStation.set('name', 'caltrain'); + const caltrainStation = new Parse.Object("Location"); + caltrainStation.set("location", caltrainStationLocation); + caltrainStation.set("name", "caltrain"); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object('Location'); - santaClara.set('location', santaClaraLocation); - santaClara.set('name', 'santa clara'); + const santaClara = new Parse.Object("Location"); + santaClara.set("location", santaClaraLocation); + santaClara.set("name", "santa clara"); 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); - caltrainStation.set('name', 'caltrain'); + const caltrainStation = new Parse.Object("Location"); + caltrainStation.set("location", caltrainStationLocation); + caltrainStation.set("name", "caltrain"); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object('Location'); - 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); + const santaClara = new Parse.Object("Location"); + 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); }); - 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); - caltrainStation.set('name', 'caltrain'); + const caltrainStation = new Parse.Object("Location"); + caltrainStation.set("location", caltrainStationLocation); + caltrainStation.set("name", "caltrain"); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object('Location'); - 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); + const santaClara = new Parse.Object("Location"); + 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); }); }); diff --git a/integration/test/ParseGeoPointTest.js b/integration/test/ParseGeoPointTest.js index cb34aad69..ea5115aa7 100644 --- a/integration/test/ParseGeoPointTest.js +++ b/integration/test/ParseGeoPointTest.js @@ -1,477 +1,515 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); -const TestPoint = Parse.Object.extend('TestPoint'); -const Container = Parse.Object.extend('Container'); +const TestObject = Parse.Object.extend("TestObject"); +const TestPoint = Parse.Object.extend("TestPoint"); +const Container = Parse.Object.extend("Container"); -describe('Geo Point', () => { +describe("Geo Point", () => { beforeAll((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); - Parse.CoreManager.set('REQUEST_ATTEMPT_LIMIT', 1); + 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('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.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(); + }); }); - 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.set("locationOne", point); + obj.set("locationTwo", point); + 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(); const point = new Parse.GeoPoint(i * 4 - 12, i * 3.2 - 11); - obj.set('location', point); - obj.set('construct', 'line'); - obj.set('seq', i); + obj.set("location", point); + obj.set("construct", "line"); + 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(); const point = new Parse.GeoPoint(i * 4 - 12, i * 3.2 - 11); - obj.set('location', point); - obj.set('construct', 'line_unsorted'); - obj.set('seq', i); + obj.set("location", point); + obj.set("construct", "line_unsorted"); + 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('index', i); + obj.set("location", point); + 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('index', i); + obj.set("location", point); + 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('index', i); + obj.set("location", point); + 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.withinKilometers("location", sfo, 4000.0); 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.withinKilometers("location", sfo, 3700.0); query.find().then((results) => { assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'San Francisco'); - assert.equal(results[1].get('name'), 'Sacramento'); + assert.equal(results[0].get("name"), "San Francisco"); + assert.equal(results[1].get("name"), "Sacramento"); done(); }); }); - 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.withinKilometers("location", sfo, 100.0); query.find().then((results) => { assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'San Francisco'); + 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.withinKilometers("location", sfo, 10.0); 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.withinMiles("location", sfo, 2500.0); 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.withinMiles("location", sfo, 2200.0); query.find().then((results) => { assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'San Francisco'); - assert.equal(results[1].get('name'), 'Sacramento'); + assert.equal(results[0].get("name"), "San Francisco"); + assert.equal(results[1].get("name"), "Sacramento"); done(); }); }); - 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.withinMiles("location", sfo, 75.0); query.find().then((results) => { assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'San Francisco'); + 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.withinMiles("location", sfo, 10.0); 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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set('location', point); - obj.set('construct', 'large_dist_unsorted'); - obj.set('index', i); + obj.set("location", point); + obj.set("construct", "large_dist_unsorted"); + 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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set('location', point); - obj.set('construct', 'medium_dist_unsorted'); - obj.set('index', i); + obj.set("location", point); + obj.set("construct", "medium_dist_unsorted"); + 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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set('location', point); - obj.set('construct', 'small_dist_unsorted'); - obj.set('index', i); + obj.set("location", point); + obj.set("construct", "small_dist_unsorted"); + 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.withinKilometers("location", sfo, 4000.0, false); 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.withinKilometers("location", sfo, 3700.0, false); query.find().then((results) => { assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'San Francisco'); - assert.equal(results[1].get('name'), 'Sacramento'); + assert.equal(results[0].get("name"), "San Francisco"); + assert.equal(results[1].get("name"), "Sacramento"); done(); }); }); - 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.withinKilometers("location", sfo, 100.0, false); query.find().then((results) => { assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'San Francisco'); + 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.withinKilometers("location", sfo, 10.0, false); 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.withinMiles("location", sfo, 2500.0, false); 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.withinMiles("location", sfo, 2200.0, false); query.find().then((results) => { assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'San Francisco'); - assert.equal(results[1].get('name'), 'Sacramento'); + assert.equal(results[0].get("name"), "San Francisco"); + assert.equal(results[1].get("name"), "Sacramento"); done(); }); }); - 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.withinMiles("location", sfo, 75.0, false); query.find().then((results) => { assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'San Francisco'); + 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.withinMiles("location", sfo, 10.0, false); 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.withinPolygon("location", points); 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.withinPolygon("location", points); 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.withinPolygon("location", 1234); 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.withinPolygon("location", [1234]); 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..28248de82 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -1,169 +1,169 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); -const sleep = require('./sleep'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); +const sleep = require("./sleep"); -const TestObject = Parse.Object.extend('TestObject'); -const DiffObject = Parse.Object.extend('DiffObject'); +const TestObject = Parse.Object.extend("TestObject"); +const DiffObject = Parse.Object.extend("DiffObject"); -describe('Parse LiveQuery', () => { +describe("Parse LiveQuery", () => { beforeEach((done) => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.User.enableUnsafeCurrentUser(); Parse.Storage._clear(); 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(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); + query.equalTo("objectId", object.id); const subscription = await query.subscribe(); - subscription.on('update', (object, original, response) => { - assert.equal(object.get('foo'), 'bar'); + subscription.on("update", (object, original, response) => { + assert.equal(object.get("foo"), "bar"); assert.equal(response.installationId, installationId); done(); - }) - object.set({ foo: 'bar' }); + }); + 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(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); + query.equalTo("objectId", object.id); const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); if (client.shouldOpen()) { client.open(); } const subscription = client.subscribe(query); - subscription.on('update', (object, original, response) => { - assert.equal(object.get('foo'), 'bar'); + subscription.on("update", (object, original, response) => { + assert.equal(object.get("foo"), "bar"); assert.equal(response.installationId, installationId); done(); }); await subscription.subscribePromise; - object.set({ foo: 'bar' }); + object.set({ foo: "bar" }); await object.save(); }); - it('can subscribe to multiple queries', async () => { + it("can subscribe to multiple queries", async () => { const objectA = new TestObject(); const objectB = new TestObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(TestObject); - queryA.equalTo('objectId', objectA.id); - queryB.equalTo('objectId', objectB.id); + queryA.equalTo("objectId", objectA.id); + queryB.equalTo("objectId", objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on('update', object => { + subscriptionA.on("update", (object) => { count++; - assert.equal(object.get('foo'), 'bar'); - }) - subscriptionB.on('update', object => { + 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' }); + assert.equal(object.get("foo"), "baz"); + }); + await objectA.save({ foo: "bar" }); + await objectB.save({ foo: "baz" }); await sleep(1000); assert.equal(count, 2); }); - it('can subscribe to multiple queries different class', async () => { + it("can subscribe to multiple queries different class", async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo('objectId', objectA.id); - queryB.equalTo('objectId', objectB.id); + queryA.equalTo("objectId", objectA.id); + queryB.equalTo("objectId", objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on('update', object => { + subscriptionA.on("update", (object) => { count++; - assert.equal(object.get('foo'), 'bar'); - }) - subscriptionB.on('update', object => { + 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' }); + assert.equal(object.get("foo"), "baz"); + }); + await objectA.save({ foo: "bar" }); + await objectB.save({ foo: "baz" }); await sleep(1000); assert.equal(count, 2); }); - it('can unsubscribe to multiple queries different class', async () => { + it("can unsubscribe to multiple queries different class", async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo('objectId', objectA.id); - queryB.equalTo('objectId', objectB.id); + queryA.equalTo("objectId", objectA.id); + queryB.equalTo("objectId", objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on('update', () => { + subscriptionA.on("update", () => { count++; - }) - subscriptionB.on('update', object => { + }); + subscriptionB.on("update", (object) => { count++; - assert.equal(object.get('foo'), 'baz'); - }) + assert.equal(object.get("foo"), "baz"); + }); subscriptionA.unsubscribe(); - await objectA.save({ foo: 'bar' }); - await objectB.save({ foo: 'baz' }); + await objectA.save({ foo: "bar" }); + await objectB.save({ foo: "baz" }); await sleep(1000); assert.equal(count, 1); }); - it('can unsubscribe with await to multiple queries different class', async () => { + it("can unsubscribe with await to multiple queries different class", async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo('objectId', objectA.id); - queryB.equalTo('objectId', objectB.id); + queryA.equalTo("objectId", objectA.id); + queryB.equalTo("objectId", objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on('update', () => { + subscriptionA.on("update", () => { count++; - }) - subscriptionB.on('update', object => { + }); + subscriptionB.on("update", (object) => { count++; - assert.equal(object.get('foo'), 'baz'); - }) + assert.equal(object.get("foo"), "baz"); + }); await subscriptionA.unsubscribe(); - await objectA.save({ foo: 'bar' }); - await objectB.save({ foo: 'baz' }); + await objectA.save({ foo: "bar" }); + await objectB.save({ foo: "baz" }); await sleep(1000); assert.equal(count, 1); }); - it('can subscribe to ACL', async (done) => { - const user = await Parse.User.signUp('ooo', 'password'); + it("can subscribe to ACL", async (done) => { + const user = await Parse.User.signUp("ooo", "password"); const ACL = new Parse.ACL(user); const object = new TestObject(); @@ -171,73 +171,73 @@ describe('Parse LiveQuery', () => { await object.save(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); + query.equalTo("objectId", object.id); const subscription = await query.subscribe(user.getSessionToken()); - subscription.on('update', async (object) => { - assert.equal(object.get('foo'), 'bar'); + subscription.on("update", async (object) => { + assert.equal(object.get("foo"), "bar"); await Parse.User.logOut(); done(); - }) - await object.save({ foo: 'bar' }); + }); + await object.save({ foo: "bar" }); }); - it('can subscribe to null sessionToken', async (done) => { - const user = await Parse.User.signUp('oooooo', 'password'); + it("can subscribe to null sessionToken", async (done) => { + const user = await Parse.User.signUp("oooooo", "password"); const readOnly = Parse.User.readOnlyAttributes(); Parse.User.readOnlyAttributes = null; - user.set('sessionToken', null); + user.set("sessionToken", null); assert.equal(user.getSessionToken(), null); const object = new TestObject(); await object.save(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); + query.equalTo("objectId", object.id); const subscription = await query.subscribe(); - subscription.on('update', async (object) => { - assert.equal(object.get('foo'), 'bar'); - Parse.User.readOnlyAttributes = function() { + subscription.on("update", async (object) => { + assert.equal(object.get("foo"), "bar"); + Parse.User.readOnlyAttributes = function () { return readOnly; }; await Parse.User.logOut(); done(); - }) - await object.save({ foo: 'bar' }); + }); + 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(); await object.save(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); + 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 }); + await object.save({ name: "hello", age: 21 }); const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); - query.select(['name']); + query.equalTo("objectId", object.id); + query.select(["name"]); const subscription = await query.subscribe(); - subscription.on('update', (object) => { - assert.equal(object.get('name'), 'hello'); - assert.equal(object.get('age'), undefined) - assert.equal(object.get('foo'), undefined); + subscription.on("update", (object) => { + assert.equal(object.get("name"), "hello"); + assert.equal(object.get("age"), undefined); + assert.equal(object.get("foo"), undefined); done(); - }) - object.set({ foo: 'bar' }); + }); + object.set({ foo: "bar" }); await object.save(); }); }); diff --git a/integration/test/ParseLocalDatastoreTest.js b/integration/test/ParseLocalDatastoreTest.js index ecfa9572a..09a390572 100644 --- a/integration/test/ParseLocalDatastoreTest.js +++ b/integration/test/ParseLocalDatastoreTest.js @@ -1,14 +1,14 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); -const TestObject = Parse.Object.extend('TestObject'); -const Item = Parse.Object.extend('Item'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); +const TestObject = Parse.Object.extend("TestObject"); +const Item = Parse.Object.extend("Item"); -global.localStorage = require('./mockLocalStorage'); -const mockRNStorage = require('./mockRNStorage'); -const LocalDatastoreUtils = require('../../lib/node/LocalDatastoreUtils'); +global.localStorage = require("./mockLocalStorage"); +const mockRNStorage = require("./mockRNStorage"); +const LocalDatastoreUtils = require("../../lib/node/LocalDatastoreUtils"); const DEFAULT_PIN = LocalDatastoreUtils.DEFAULT_PIN; const PIN_PREFIX = LocalDatastoreUtils.PIN_PREFIX; @@ -39,10 +39,10 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName('DO_NOT_CLEAR', {}); + await Parse.LocalDatastore.pinWithName("DO_NOT_CLEAR", {}); let storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); @@ -51,8 +51,8 @@ function runTest(controller) { storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 1); - assert.equal(storage['DO_NOT_CLEAR'], '{}'); - await Parse.LocalDatastore.unPinWithName('DO_NOT_CLEAR'); + assert.equal(storage["DO_NOT_CLEAR"], "{}"); + await Parse.LocalDatastore.unPinWithName("DO_NOT_CLEAR"); }); it(`${controller.name} can getAllContents localDatastore`, async () => { @@ -61,17 +61,17 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName('DO_NOT_FETCH', {}); + await Parse.LocalDatastore.pinWithName("DO_NOT_FETCH", {}); const storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); const LDS = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(LDS).length, 5); - assert.equal(LDS['DO_NOT_FETCH'], null); + assert.equal(LDS["DO_NOT_FETCH"], null); }); it(`${controller.name} can pin (unsaved)`, async () => { @@ -81,7 +81,9 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); - assert.deepEqual(localDatastore[LDS_KEY(object)], [LDS_FULL_JSON(object)]); + assert.deepEqual(localDatastore[LDS_KEY(object)], [ + LDS_FULL_JSON(object), + ]); await object.save(); // Check if localDatastore updated localId to objectId localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -92,7 +94,7 @@ function runTest(controller) { it(`${controller.name} can store data to pin (unsaved)`, async () => { const object = new TestObject(); - object.set('foo', 'bar'); + object.set("foo", "bar"); await object.pin(); const query = new Parse.Query(TestObject); @@ -101,19 +103,19 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'bar'); - pinnedObject.set('foo', 'baz'); + assert.equal(pinnedObject.get("foo"), "bar"); + pinnedObject.set("foo", "baz"); await pinnedObject.pin(); results = await query.find(); assert.equal(results.length, 1); pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'baz'); + assert.equal(pinnedObject.get("foo"), "baz"); }); it(`${controller.name} can query unsaved pin and save`, async () => { const object = new TestObject(); - object.set('foo', 'bar'); + object.set("foo", "bar"); await object.pin(); const query = new Parse.Query(TestObject); @@ -123,9 +125,9 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'bar'); + assert.equal(pinnedObject.get("foo"), "bar"); - pinnedObject.set('foo', 'baz'); + pinnedObject.set("foo", "baz"); await pinnedObject.save(); assert(pinnedObject.id); @@ -134,7 +136,7 @@ function runTest(controller) { results = await query.find(); pinnedObject = results[0]; - assert.equal(pinnedObject.get('foo'), 'baz'); + assert.equal(pinnedObject.get("foo"), "baz"); assert(pinnedObject.id); assert.equal(pinnedObject._localId, undefined); }); @@ -142,13 +144,13 @@ function runTest(controller) { it(`${controller.name} can pin unsaved pointer`, async () => { const object = new TestObject(); const pointer = new Item(); - object.set('child', pointer); + object.set("child", pointer); await object.pin(); }); it(`${controller.name} can pin user (unsaved)`, async () => { const user = new Parse.User(); - user.set('field', 'test'); + user.set("field", "test"); await user.pin(); const json = user._toFullJSON(); @@ -160,16 +162,16 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); await Parse.User.logOut(); }); it(`${controller.name} can pin user (saved)`, async () => { const user = new Parse.User(); - user.set('field', 'test'); - user.setPassword('asdf'); - user.setUsername('zxcv'); - await user.signUp() + user.set("field", "test"); + user.setPassword("asdf"); + user.setUsername("zxcv"); + await user.signUp(); await user.pin(); const json = user._toFullJSON(); @@ -182,13 +184,13 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); await Parse.User.logOut(); }); it(`${controller.name} can pin (saved)`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); await object.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -197,16 +199,16 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, 'test'); + assert.equal(cachedObject.field, "test"); }); it(`${controller.name} can pin (twice saved)`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); await object.pin(); - object.set('field', 'new info'); + object.set("field", "new info"); await object.save(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -215,12 +217,12 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, 'new info'); + assert.equal(cachedObject.field, "new info"); }); it(`${controller.name} can check if pinned`, async () => { const object = new TestObject(); - object.set('field', 'test'); + object.set("field", "test"); await object.save(); let isPinned = await object.isPinned(); @@ -239,29 +241,34 @@ function runTest(controller) { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set('grandchild', grandchild); - parent.set('field', 'test'); - parent.set('child', child); + child.set("grandchild", grandchild); + parent.set("field", "test"); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(parent)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), true); + assert.equal( + localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), + true + ); assert.deepEqual(localDatastore[LDS_KEY(parent)], [parent._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(child)], [child._toFullJSON()]); - assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [grandchild._toFullJSON()]); + assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [ + grandchild._toFullJSON(), + ]); }); it(`${controller.name} can pin user (recursive)`, async () => { const parent = new TestObject(); const child = new Parse.User(); - child.setUsername('username'); - child.setPassword('password'); + child.setUsername("username"); + child.setPassword("password"); await child.signUp(); - parent.set('field', 'test'); - parent.set('child', child); + parent.set("field", "test"); + parent.set("child", child); await parent.save(); await parent.pin(); @@ -289,7 +296,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -298,7 +309,11 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -315,7 +330,11 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -327,11 +346,15 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); 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 +363,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()]); @@ -353,10 +380,14 @@ function runTest(controller) { const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + 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()]); @@ -367,8 +398,8 @@ function runTest(controller) { const obj2 = new TestObject(); await obj1.pin(); await obj2.pin(); - await obj1.pinWithName('test_pin'); - await obj2.pinWithName('test_pin'); + await obj1.pinWithName("test_pin"); + await obj2.pinWithName("test_pin"); await Parse.Object.saveAll([obj1, obj2]); @@ -376,8 +407,14 @@ function runTest(controller) { assert(Object.keys(localDatastore).length === 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); @@ -386,7 +423,9 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + LDS_KEY(obj2), + ]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -396,7 +435,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -404,9 +443,18 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -416,7 +464,9 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + LDS_KEY(obj2), + ]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -430,7 +480,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -439,7 +493,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -447,7 +504,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -462,7 +522,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -473,7 +537,10 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [ + LDS_KEY(obj1), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); }); @@ -522,7 +589,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -552,7 +623,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -576,7 +651,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -608,7 +687,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -629,27 +712,35 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); - await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); + await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); await Parse.Object.saveAll(objects); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -659,21 +750,27 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); + await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -683,16 +780,20 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); - await Parse.Object.unPinAllObjectsWithName('test_unpin'); + await Parse.Object.unPinAllObjectsWithName("test_unpin"); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); @@ -715,18 +816,22 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName('test_unpin', objects); + await Parse.Object.pinAllWithName("test_unpin", objects); 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)]); await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllObjectsWithName('test_unpin'); + await Parse.Object.unPinAllObjectsWithName("test_unpin"); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); @@ -740,7 +845,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -748,9 +853,18 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -766,11 +880,11 @@ function runTest(controller) { const obj2 = new TestObject(); const obj3 = new TestObject(); const child = new TestObject(); - obj1.set('child', child); + obj1.set("child", child); const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 6); @@ -778,10 +892,22 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); - assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(child)), true); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), + true + ); + assert.equal( + localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(child)), + true + ); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -799,7 +925,7 @@ function runTest(controller) { const object = new TestObject(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); + assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); } }); @@ -809,7 +935,7 @@ function runTest(controller) { await object.pin(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); + assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); } }); @@ -817,8 +943,8 @@ function runTest(controller) { const obj1 = new TestObject(); const obj2 = new TestObject(); - obj1.set('field', 'test'); - obj1.set('foo', 'bar'); + obj1.set("field", "test"); + obj1.set("foo", "bar"); await obj1.pin(); await obj1.save(); @@ -833,10 +959,10 @@ function runTest(controller) { assert.deepEqual(obj1._toFullJSON(), obj3._toFullJSON()); const obj4 = TestObject.createWithoutData(obj1.id); - obj4.set('field', 'will not override'); + obj4.set("field", "will not override"); await obj4.fetchFromLocalDatastore(); - assert.equal(obj4.get('field'), 'will not override'); - assert.equal(obj4.get('foo'), 'bar'); + assert.equal(obj4.get("field"), "will not override"); + assert.equal(obj4.get("foo"), "bar"); }); it(`${controller.name} can fetchFromLocalDatastore with children`, async () => { @@ -845,14 +971,14 @@ function runTest(controller) { const child = new TestObject(); const grandchild = new TestObject(); - obj1.set('field', 'test'); - obj1.set('child', child); + obj1.set("field", "test"); + obj1.set("child", child); await obj1.save(); await obj1.pin(); - grandchild.set('field', 'shouldAlsoHave'); - child.set('field', 'shouldHave'); - child.set('grandchild', grandchild); + grandchild.set("field", "shouldAlsoHave"); + child.set("field", "shouldHave"); + child.set("grandchild", grandchild); await child.save(); obj2.id = obj1.id; @@ -860,16 +986,16 @@ function runTest(controller) { assert.deepEqual(obj1.toJSON(), obj2.toJSON()); assert.deepEqual(obj1._toFullJSON(), obj2._toFullJSON()); - assert.deepEqual(obj2.toJSON().child.field, 'shouldHave'); - assert.deepEqual(obj2.toJSON().child.grandchild.field, 'shouldAlsoHave'); + assert.deepEqual(obj2.toJSON().child.field, "shouldHave"); + assert.deepEqual(obj2.toJSON().child.grandchild.field, "shouldAlsoHave"); }); 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]); /* @@ -885,14 +1011,14 @@ function runTest(controller) { | C */ - A.set('B', B); - A.set('C', C); - A.set('E', E); - A.set('D', D); - B.set('A', A); - C.set('D', D); - D.set('C', C); - E.set('C', C); + A.set("B", B); + A.set("C", C); + A.set("E", E); + A.set("D", D); + B.set("A", A); + C.set("D", D); + D.set("C", C); + E.set("C", C); await Parse.Object.saveAll([A, B, C, D, E]); await A.pin(); @@ -902,23 +1028,23 @@ function runTest(controller) { await object.fetchFromLocalDatastore(); const root = object.toJSON(); - assert.deepEqual(root.B.A.__type, 'Pointer'); - assert.deepEqual(root.C.D.C.__type, 'Pointer'); - assert.deepEqual(root.E.C.__type, 'Object'); - assert.deepEqual(root.D.__type, 'Object'); + assert.deepEqual(root.B.A.__type, "Pointer"); + assert.deepEqual(root.C.D.C.__type, "Pointer"); + assert.deepEqual(root.E.C.__type, "Object"); + assert.deepEqual(root.D.__type, "Object"); }); - it('fetch updates LocalDatastore', async () => { - const item = new Item({ foo: 'bar' }); + it("fetch updates LocalDatastore", async () => { + const item = new Item({ foo: "bar" }); await item.save(); await item.pin(); const params = { id: item.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'bar'); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, "bar"); const itemAgain = new Item(); itemAgain.id = item.id; @@ -926,58 +1052,61 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(itemAgain.get('foo'), 'changed'); - assert.equal(fetchedItem.get('foo'), 'changed'); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'changed'); + assert.equal(itemAgain.get("foo"), "changed"); + assert.equal(fetchedItem.get("foo"), "changed"); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, "changed"); }); - it('fetchAll updates LocalDatastore', async () => { - const item1 = new Item({ foo: 'bar' }); - const item2 = new Item({ foo: 'baz' }); + it("fetchAll updates LocalDatastore", async () => { + const item1 = new Item({ foo: "bar" }); + const item2 = new Item({ foo: "baz" }); await Parse.Object.saveAll([item1, item2]); await Parse.Object.pinAll([item1, item2]); let params = { id: item1.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); params = { id: item2.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item1)][0].foo, 'bar'); - assert.equal(localDatastore[LDS_KEY(item2)][0].foo, 'baz'); + assert.equal(localDatastore[LDS_KEY(item1)][0].foo, "bar"); + assert.equal(localDatastore[LDS_KEY(item2)][0].foo, "baz"); const item1Again = new Item(); item1Again.id = item1.id; const item2Again = new Item(); item2Again.id = item2.id; - const fetchedItems = await Parse.Object.fetchAll([item1Again, item2Again]); + const fetchedItems = await Parse.Object.fetchAll([ + item1Again, + item2Again, + ]); localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(item1Again.get('foo'), 'changed'); - assert.equal(item2Again.get('foo'), 'changed'); - assert.equal(fetchedItems[0].get('foo'), 'changed'); - assert.equal(fetchedItems[1].get('foo'), 'changed'); - assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, 'changed'); - assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, 'changed'); + assert.equal(item1Again.get("foo"), "changed"); + assert.equal(item2Again.get("foo"), "changed"); + assert.equal(fetchedItems[0].get("foo"), "changed"); + assert.equal(fetchedItems[1].get("foo"), "changed"); + assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, "changed"); + assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, "changed"); }); it(`${controller.name} can update Local Datastore from network`, async () => { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set('grandchild', grandchild); - parent.set('field', 'test'); - parent.set('child', child); + child.set("grandchild", grandchild); + parent.set("field", "test"); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); // Updates child with { foo: 'changed' } const params = { id: child.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); Parse.LocalDatastore.isSyncing = false; @@ -985,7 +1114,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const childJSON = updatedLDS[LDS_KEY(child)]; - assert.equal(childJSON.foo, 'changed'); + assert.equal(childJSON.foo, "changed"); }); it(`${controller.name} can update Local Datastore from network ignore unsaved`, async () => { @@ -996,7 +1125,7 @@ function runTest(controller) { // Updates item with { foo: 'changed' } const params = { id: item.id }; - await Parse.Cloud.run('TestFetchFromLocalDatastore', params); + await Parse.Cloud.run("TestFetchFromLocalDatastore", params); Parse.LocalDatastore.isSyncing = false; @@ -1004,19 +1133,19 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const itemJSON = updatedLDS[LDS_KEY(item)]; - assert.equal(itemJSON.foo, 'changed'); + assert.equal(itemJSON.foo, "changed"); }); it(`${controller.name} can update Local Datastore User from network`, async () => { const user = new Parse.User(); - user.setUsername('asdf'); - user.setPassword('zxcv'); + user.setUsername("asdf"); + user.setPassword("zxcv"); await user.signUp(); await user.pin(); // Updates user with { foo: 'changed' } const params = { id: user.id }; - await Parse.Cloud.run('UpdateUser', params); + await Parse.Cloud.run("UpdateUser", params); Parse.LocalDatastore.isSyncing = false; @@ -1024,7 +1153,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const userJSON = updatedLDS[LDS_KEY(user)]; - assert.equal(userJSON.foo, 'changed'); + assert.equal(userJSON.foo, "changed"); await Parse.User.logOut(); }); }); @@ -1039,7 +1168,7 @@ function runTest(controller) { const numbers = []; for (let i = 0; i < 10; i++) { - numbers[i] = new Parse.Object({ className: 'BoxedNumber', number: i }); + numbers[i] = new Parse.Object({ className: "BoxedNumber", number: i }); } await Parse.Object.saveAll(numbers); await Parse.Object.pinAll(numbers); @@ -1053,15 +1182,15 @@ function runTest(controller) { const objects = [obj1, obj2, obj3, item]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName('test_pin', objects); + await Parse.Object.pinAllWithName("test_pin", objects); const query = new Parse.Query(TestObject); - query.greaterThan('field', 1); - query.fromPinWithName('test_pin'); + query.greaterThan("field", 1); + query.fromPinWithName("test_pin"); const results = await query.find(); assert.equal(results.length, 2); - assert(results[0].get('field') > 1); - assert(results[1].get('field') > 1); + assert(results[0].get("field") > 1); + assert(results[1].get("field") > 1); }); it(`${controller.name} can query from local datastore`, async () => { @@ -1089,7 +1218,7 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); await obj4.save(); - await obj4.pinWithName('DO_NOT_QUERY'); + await obj4.pinWithName("DO_NOT_QUERY"); const query = new Parse.Query(TestObject); query.fromPin(); @@ -1099,7 +1228,7 @@ function runTest(controller) { }); it(`${controller.name} can query user from pin`, async () => { - const user = await Parse.User.signUp('asdf', 'zxcv', { foo: 'bar' }); + const user = await Parse.User.signUp("asdf", "zxcv", { foo: "bar" }); await user.pin(); const query = new Parse.Query(Parse.User); @@ -1112,22 +1241,22 @@ function runTest(controller) { }); it(`${controller.name} can do basic queries`, async () => { - const baz = new TestObject({ foo: 'baz' }); - const qux = new TestObject({ foo: 'qux' }); + const baz = new TestObject({ foo: "baz" }); + const qux = new TestObject({ foo: "qux" }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); - query.equalTo('foo', 'baz'); + query.equalTo("foo", "baz"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('foo'), 'baz'); + assert.equal(results[0].get("foo"), "baz"); }); it(`${controller.name} can do a query with a limit`, async () => { - const baz = new TestObject({ foo: 'baz' }); - const qux = new TestObject({ foo: 'qux' }); + const baz = new TestObject({ foo: "baz" }); + const qux = new TestObject({ foo: "qux" }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); @@ -1136,64 +1265,64 @@ function runTest(controller) { const results = await query.find(); assert.equal(results.length, 1); - assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); + assert.equal(["baz", "qux"].includes(results[0].get("foo")), true); }); it(`${controller.name} can do equalTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 3); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it('can do containedBy queries with numbers', async () => { + 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); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('containedBy', true); - query.containedBy('numbers', [1, 2, 3, 4, 5]); + query.equalTo("containedBy", true); + query.containedBy("numbers", [1, 2, 3, 4, 5]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it('can do containedBy queries with pointer', async () => { + it("can do containedBy queries with pointer", async () => { const objects = Array.from(Array(10).keys()).map((idx) => { - const obj = new Parse.Object('Object'); - obj.set('key', idx); + const obj = new Parse.Object("Object"); + obj.set("key", idx); return obj; }); - const parent1 = new Parse.Object('Parent'); - const parent2 = new Parse.Object('Parent'); - const parent3 = new Parse.Object('Parent'); + const parent1 = new Parse.Object("Parent"); + const parent2 = new Parse.Object("Parent"); + const parent3 = new Parse.Object("Parent"); await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); // [0, 1, 2] - parent1.set('objects', objects.slice(0, 3)); + parent1.set("objects", objects.slice(0, 3)); const shift = objects.shift(); // [2, 0] - parent2.set('objects', [objects[1], shift]); + parent2.set("objects", [objects[1], shift]); // [1, 2, 3, 4] - parent3.set('objects', objects.slice(1, 4)); + parent3.set("objects", objects.slice(1, 4)); await Parse.Object.saveAll([parent1, parent2, parent3]); await Parse.Object.pinAll([parent1, parent2, parent3]); - const query = new Parse.Query('Parent'); - query.containedBy('objects', objects); + const query = new Parse.Query("Parent"); + query.containedBy("objects", objects); query.fromLocalDatastore(); const results = await query.find(); @@ -1202,125 +1331,129 @@ function runTest(controller) { }); it(`${controller.name} can test equality with undefined`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', undefined); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", undefined); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} can perform lessThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThan("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 7); }); it(`${controller.name} can perform lessThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 8); }); it(`${controller.name} can perform greaterThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.greaterThan("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); }); it(`${controller.name} can perform greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.greaterThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 3); }); it(`${controller.name} can combine lessThanOrEqualTo and greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); - query.greaterThanOrEqualTo('number', 7); + const query = new Parse.Query("BoxedNumber"); + query.lessThanOrEqualTo("number", 7); + query.greaterThanOrEqualTo("number", 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); it(`${controller.name} can combine lessThan and greaterThan queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 9); - query.greaterThan('number', 3); + const query = new Parse.Query("BoxedNumber"); + query.lessThan("number", 9); + query.greaterThan("number", 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); }); it(`${controller.name} can perform notEqualTo queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.notEqualTo('number', 5); + const query = new Parse.Query("BoxedNumber"); + query.notEqualTo("number", 5); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 9); }); it(`${controller.name} can perform containedIn queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.containedIn('number', [3,5,7,9,11]); + const query = new Parse.Query("BoxedNumber"); + query.containedIn("number", [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 4); }); it(`${controller.name} can perform notContainedIn queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.notContainedIn('number', [3,5,7,9,11]); + const query = new Parse.Query("BoxedNumber"); + query.notContainedIn("number", [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 6); }); it(`${controller.name} can test objectId in containedIn queries`, async () => { - const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); - const ids = [numbers[2].id, numbers[3].id, 'nonsense']; - const query = new Parse.Query('BoxedNumber'); - query.containedIn('objectId', ids); - query.ascending('number'); + const numbers = await new Parse.Query("BoxedNumber") + .ascending("number") + .find(); + const ids = [numbers[2].id, numbers[3].id, "nonsense"]; + const query = new Parse.Query("BoxedNumber"); + query.containedIn("objectId", ids); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); - assert.equal(results[0].get('number'), 2); - assert.equal(results[1].get('number'), 3); + assert.equal(results[0].get("number"), 2); + assert.equal(results[1].get("number"), 3); }); it(`${controller.name} can test objectId in equalTo queries`, async () => { - const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); + const numbers = await new Parse.Query("BoxedNumber") + .ascending("number") + .find(); const id = numbers[5].id; - const query = new Parse.Query('BoxedNumber'); - query.equalTo('objectId', id); - query.ascending('number'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("objectId", id); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('number'), 5); + assert.equal(results[0].get("number"), 5); }); it(`${controller.name} can find no elements`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 15); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 15); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} handles when find throws errors`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); query.fromLocalDatastore(); try { await query.find(); @@ -1352,42 +1485,42 @@ 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); } }); it(`${controller.name} can query for the first result`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.descending('number'); + const query = new Parse.Query("BoxedNumber"); + query.descending("number"); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get('number'), 9); + assert.equal(result.get("number"), 9); }); it(`${controller.name} can query for the first with no results`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 20); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 20); query.fromLocalDatastore(); const result = await query.first(); assert.equal(result, undefined); }); 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); - query.equalTo('x', 44); + query.equalTo("x", 44); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get('x'), 44); + assert.equal(result.get("x"), 44); }); it(`${controller.name} handles when first throws errors`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); try { query.fromLocalDatastore(); await query.first(); @@ -1400,13 +1533,19 @@ 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); - const query = new Parse.Query('CoolContainer'); - query.notEqualTo('item', item1); + const query = new Parse.Query("CoolContainer"); + query.notEqualTo("item", item1); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -1422,14 +1561,14 @@ function runTest(controller) { await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); + query.equalTo("canSkip", true); query.skip(1); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); + query.equalTo("canSkip", true); query.skip(3); query.fromLocalDatastore(); results = await query.find(); @@ -1440,23 +1579,23 @@ 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); + query.equalTo("skipCount", true); query.fromLocalDatastore(); let count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); + query.equalTo("skipCount", true); query.skip(1); query.fromLocalDatastore(); count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); + query.equalTo("skipCount", true); query.skip(2); query.fromLocalDatastore(); count = await query.count(); @@ -1464,164 +1603,163 @@ function runTest(controller) { }); it(`${controller.name} can perform count queries`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 1); + 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); }); it(`${controller.name} can order by ascending numbers`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('number'); + const query = new Parse.Query("BoxedNumber"); + query.ascending("number"); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get('number'), 0); - assert.equal(results[9].get('number'), 9); + assert.equal(results[0].get("number"), 0); + assert.equal(results[9].get("number"), 9); }); it(`${controller.name} can order by descending numbers`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.descending('number'); + const query = new Parse.Query("BoxedNumber"); + query.descending("number"); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get('number'), 9); - assert.equal(results[9].get('number'), 0); + assert.equal(results[0].get("number"), 9); + assert.equal(results[9].get("number"), 0); }); it(`${controller.name} can order by ascending number then descending string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('doubleOrder', true); - query.ascending('number').addDescending('string'); + query.equalTo("doubleOrder", true); + query.ascending("number").addDescending("string"); query.fromLocalDatastore(); const results = await query.find(); 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'); + 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"); }); it(`${controller.name} can order by descending number then ascending string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('otherDoubleOrder', true); - query.descending('number').addAscending('string'); + query.equalTo("otherDoubleOrder", true); + query.descending("number").addAscending("string"); query.fromLocalDatastore(); const results = await query.find(); 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'); + 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"); }); it(`${controller.name} can order by descending number and string`, async () => { const objects = [ - 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' }), + 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" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number,string'); + query.equalTo("doubleDescending", true); + query.descending("number,string"); query.fromLocalDatastore(); let results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number, string'); + query.equalTo("doubleDescending", true); + query.descending("number, string"); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending(['number', 'string']); + query.equalTo("doubleDescending", true); + query.descending(["number", "string"]); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number', 'string'); + query.equalTo("doubleDescending", true); + query.descending("number", "string"); query.fromLocalDatastore(); results = await query.find(); 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'); + 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"); }); - it(`${controller.name} can not order by password`, async () => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('_password'); + const query = new Parse.Query("BoxedNumber"); + query.ascending("_password"); query.fromLocalDatastore(); try { await query.find(); @@ -1632,16 +1770,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate', true); - query.ascending('_created_at'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate", true); + query.ascending("_created_at"); query.fromLocalDatastore(); const results = await query.find(); @@ -1651,16 +1801,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate2', true); - query.descending('createdAt'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate2", true); + query.descending("createdAt"); query.fromLocalDatastore(); const results = await query.find(); @@ -1670,16 +1832,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate3', true); - query.ascending('_updated_at'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate3", true); + query.ascending("_updated_at"); query.fromLocalDatastore(); const results = await query.find(); @@ -1689,16 +1863,28 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate4', true); - query.ascending('updatedAt'); + const query = new Parse.Query("TestObject"); + query.equalTo("orderedDate4", true); + query.ascending("updatedAt"); query.fromLocalDatastore(); const results = await query.find(); @@ -1708,35 +1894,67 @@ 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]); - const query = new Parse.Query('TestObject'); - query.equalTo('timed', true); - query.equalTo('createdAt', last.createdAt); + const query = new Parse.Query("TestObject"); + query.equalTo("timed", true); + query.equalTo("createdAt", last.createdAt); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'item4'); + assert.equal(results[0].get("name"), "item4"); }); 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]); - let query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.lessThan('createdAt', obj3.createdAt); - query.ascending('createdAt'); + let query = new Parse.Query("TestObject"); + query.equalTo("timed2", true); + query.lessThan("createdAt", obj3.createdAt); + query.ascending("createdAt"); query.fromLocalDatastore(); let results = await query.find(); @@ -1744,9 +1962,9 @@ function runTest(controller) { assert.equal(results[0].id, obj1.id); assert.equal(results[1].id, obj2.id); - query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.greaterThan('createdAt', obj3.createdAt); + query = new Parse.Query("TestObject"); + query.equalTo("timed2", true); + query.greaterThan("createdAt", obj3.createdAt); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); @@ -1755,43 +1973,43 @@ function runTest(controller) { it(`${controller.name} can test string matching`, async () => { const obj1 = new TestObject(); - obj1.set('myString', 'football'); + obj1.set("myString", "football"); const obj2 = new TestObject(); - obj2.set('myString', 'soccer'); + obj2.set("myString", "soccer"); await Parse.Object.saveAll([obj1, obj2]); await Parse.Object.pinAll([obj1, obj2]); let query = new Parse.Query(TestObject); - query.matches('myString', '^fo*\\wb[^o]l+$'); + query.matches("myString", "^fo*\\wb[^o]l+$"); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); + assert.equal(results[0].get("myString"), "football"); query = new Parse.Query(TestObject); - query.matches('myString', /^fo*\wb[^o]l+$/); + query.matches("myString", /^fo*\wb[^o]l+$/); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); + assert.equal(results[0].get("myString"), "football"); }); it(`${controller.name} can test case insensitive regex`, async () => { const obj = new TestObject(); - obj.set('myString', 'hockey'); + obj.set("myString", "hockey"); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.matches('myString', 'Hockey', 'i'); + query.matches("myString", "Hockey", "i"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'hockey'); + assert.equal(results[0].get("myString"), "hockey"); }); it(`${controller.name} fails for invalid regex options`, async () => { const query = new Parse.Query(TestObject); - query.matches('myString', 'football', 'some invalid thing'); + query.matches("myString", "football", "some invalid thing"); query.fromLocalDatastore(); try { await query.find(); @@ -1803,12 +2021,12 @@ function runTest(controller) { it(`${controller.name} can use a regex with all modifiers`, async () => { const obj = new TestObject(); - obj.set('website', '\n\nbuffer\n\nparse.COM'); + obj.set("website", "\n\nbuffer\n\nparse.COM"); await obj.save(); 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); @@ -1816,39 +2034,40 @@ function runTest(controller) { it(`${controller.name} can include regexp modifiers in the constructor`, async () => { const obj = new TestObject(); - obj.set('website', '\n\nbuffer\n\nparse.COM'); + obj.set("website", "\n\nbuffer\n\nparse.COM"); await obj.save(); 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); let query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); + query.equalTo("contains", true); + query.startsWith("myString", someAscii); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); + query.equalTo("contains", true); + query.startsWith("myString", someAscii); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 2); @@ -1859,9 +2078,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject(); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } objects.push(item); } @@ -1869,12 +2088,12 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.exists('y'); + query.exists("y"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); + assert(results[i].has("y")); } }); @@ -1883,9 +2102,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject({ dne: true }); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } objects.push(item); } @@ -1893,26 +2112,28 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo('dne', true); - query.doesNotExist('y'); + query.equalTo("dne", true); + query.doesNotExist("y"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('z')); + assert(results[i].has("z")); } }); 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); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } objects.push(container); @@ -1920,27 +2141,27 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query('Container'); - query.equalTo('relation_exists', true); - query.exists('x'); + const query = new Parse.Query("Container"); + query.equalTo("relation_exists", true); + query.exists("x"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('x')); + assert(results[i].has("x")); } }); it(`${controller.name} can test if a relation does not exist`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const container = new Parse.Object('Container', { relation_dne: true }); + const container = new Parse.Object("Container", { relation_dne: true }); if (i % 2) { - container.set('y', i); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } objects.push(container); @@ -1948,14 +2169,14 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query('Container'); - query.equalTo('relation_dne', true); - query.doesNotExist('x'); + const query = new Parse.Query("Container"); + query.equalTo("relation_dne", true); + query.doesNotExist("x"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); + assert(results[i].has("y")); } }); @@ -1981,96 +2202,96 @@ function runTest(controller) { it(`${controller.name} can include nested objects`, async () => { const child = new TestObject(); - const parent = new Parse.Object('Container'); - child.set('foo', 'bar'); - parent.set('child', child); + const parent = new Parse.Object("Container"); + child.set("foo", "bar"); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include('child'); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); + query.include("child"); query.fromLocalDatastore(); const results = await query.find(); 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'); + assert(parentAgain.get("child")); + assert(parentAgain.get("child").id); + assert.equal(parentAgain.get("child").get("foo"), "bar"); }); it(`${controller.name} can includeAll nested objects`, async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); await Parse.Object.pinAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - assert.equal(parentAgain.get('child1').get('foo'), 'bar'); - assert.equal(parentAgain.get('child2').get('foo'), 'baz'); - assert.equal(parentAgain.get('child3').get('foo'), 'bin'); + assert.equal(parentAgain.get("child1").get("foo"), "bar"); + assert.equal(parentAgain.get("child2").get("foo"), "baz"); + assert.equal(parentAgain.get("child3").get("foo"), "bin"); }); it(`${controller.name} can includeAll nested objects in .each`, async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); query.fromLocalDatastore(); 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'); + assert.equal(obj.get("child1").get("foo"), "bar"); + assert.equal(obj.get("child2").get("foo"), "baz"); + assert.equal(obj.get("child3").get("foo"), "bin"); }); }); it(`${controller.name} can include nested objects via array`, async () => { const child = new TestObject(); - const parent = new Parse.Object('Container'); - child.set('foo', 'bar'); - parent.set('child', child); + const parent = new Parse.Object("Container"); + child.set("foo", "bar"); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include(['child']); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); + query.include(["child"]); query.fromLocalDatastore(); const results = await query.find(); 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'); + assert(parentAgain.get("child")); + assert(parentAgain.get("child").id); + assert.equal(parentAgain.get("child").get("foo"), "bar"); }); it(`${controller.name} can do a nested include`, async () => { - const Child = Parse.Object.extend('Child'); - const Parent = Parse.Object.extend('Parent'); - const Grandparent = Parse.Object.extend('Grandparent'); + const Child = Parse.Object.extend("Child"); + const Parent = Parse.Object.extend("Parent"); + const Grandparent = Parse.Object.extend("Grandparent"); const objects = []; for (let i = 0; i < 5; i++) { @@ -2080,7 +2301,7 @@ function runTest(controller) { parent: new Parent({ y: i, child: new Child({ - x: i + x: i, }), }), }); @@ -2091,315 +2312,321 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q = new Parse.Query('Grandparent'); - q.equalTo('nested', true); - q.include('parent.child'); + const q = new Parse.Query("Grandparent"); + q.equalTo("nested", true); + q.include("parent.child"); q.fromLocalDatastore(); const results = await q.find(); 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')); + assert.equal(o.get("z"), o.get("parent").get("y")); + assert.equal(o.get("z"), o.get("parent").get("child").get("x")); }); }); it(`${controller.name} can include without changing dirty`, async () => { - const parent = new Parse.Object('ParentObject'); - const child = new Parse.Object('ChildObject'); - parent.set('child', child); - child.set('foo', 'bar'); + const parent = new Parse.Object("ParentObject"); + const child = new Parse.Object("ChildObject"); + parent.set("child", child); + child.set("foo", "bar"); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query('ParentObject'); - query.include('child'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("ParentObject"); + query.include("child"); + query.equalTo("objectId", parent.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); + const childAgain = parentAgain.get("child"); assert.equal(child.id, childAgain.id); assert.equal(parent.id, parentAgain.id); - assert.equal(childAgain.get('foo'), 'bar'); + assert.equal(childAgain.get("foo"), "bar"); assert(!parentAgain.dirty()); assert(!childAgain.dirty()); }); it(`${controller.name} uses subclasses when creating objects`, async () => { - const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); - let ChildObject = Parse.Object.extend('ChildObject', { + const ParentObject = Parse.Object.extend({ className: "ParentObject" }); + let ChildObject = Parse.Object.extend("ChildObject", { foo() { - return 'foo'; - } + return "foo"; + }, }); const parent = new ParentObject(); const child = new ChildObject(); - parent.set('child', child); + parent.set("child", child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - ChildObject = Parse.Object.extend('ChildObject', { + ChildObject = Parse.Object.extend("ChildObject", { bar() { - return 'bar'; - } + return "bar"; + }, }); const query = new Parse.Query(ParentObject); - query.equalTo('objectId', parent.id); - query.include('child'); + query.equalTo("objectId", parent.id); + query.include("child"); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); - assert.equal(childAgain.foo(), 'foo'); - assert.equal(childAgain.bar(), 'bar'); + const childAgain = parentAgain.get("child"); + assert.equal(childAgain.foo(), "foo"); + assert.equal(childAgain.bar(), "bar"); }); it(`${controller.name} can match the results of another query`, async () => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('qtest', true); - subQuery.greaterThan('x', 5); + subQuery.equalTo("qtest", true); + subQuery.greaterThan("x", 5); const q = new Parse.Query(ParentObject); - q.matchesQuery('child', subQuery); + q.matchesQuery("child", subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 4); results.forEach((o) => { - assert(o.get('x') > 15); + assert(o.get("x") > 15); }); }); it(`${controller.name} can not match the results of another query`, async () => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('dneqtest', true); - subQuery.greaterThan('x', 5); + subQuery.equalTo("dneqtest", true); + subQuery.greaterThan("x", 5); const q = new Parse.Query(ParentObject); - q.equalTo('dneqtest', true); - q.doesNotMatchQuery('child', subQuery); + q.equalTo("dneqtest", true); + q.doesNotMatchQuery("child", subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 6); results.forEach((o) => { - assert(o.get('x') >= 10); - assert(o.get('x') <= 15); + assert(o.get("x") >= 10); + assert(o.get("x") <= 15); }); }); it(`${controller.name} can select keys from a matched query`, async () => { - const Restaurant = Parse.Object.extend('Restaurant'); - const Person = Parse.Object.extend('Person'); + const Restaurant = Parse.Object.extend("Restaurant"); + const Person = Parse.Object.extend("Person"); const objects = [ - new Restaurant({ rating: 5, location: 'Djibouti' }), - new Restaurant({ rating: 3, location: 'Ouagadougou' }), - new Person({ name: 'Bob', hometown: 'Djibouti' }), - new Person({ name: 'Tom', hometown: 'Ouagadougou' }), - new Person({ name: 'Billy', hometown: 'Detroit' }), + new Restaurant({ rating: 5, location: "Djibouti" }), + new Restaurant({ rating: 3, location: "Ouagadougou" }), + new Person({ name: "Bob", hometown: "Djibouti" }), + new Person({ name: "Tom", hometown: "Ouagadougou" }), + new Person({ name: "Billy", hometown: "Detroit" }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); + query.greaterThan("rating", 4); let mainQuery = new Parse.Query(Person); - mainQuery.matchesKeyInQuery('hometown', 'location', query); + mainQuery.matchesKeyInQuery("hometown", "location", query); mainQuery.fromLocalDatastore(); let results = await mainQuery.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'Bob'); + assert.equal(results[0].get("name"), "Bob"); query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); + query.greaterThan("rating", 4); mainQuery = new Parse.Query(Person); - mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); - mainQuery.ascending('name'); + mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); + mainQuery.ascending("name"); mainQuery.fromLocalDatastore(); results = await mainQuery.find(); assert.equal(results.length, 2); - assert(['Billy', 'Tom'].includes(results[0].get('name'))); - assert(['Billy', 'Tom'].includes(results[1].get('name'))); + assert(["Billy", "Tom"].includes(results[0].get("name"))); + assert(["Billy", "Tom"].includes(results[1].get("name"))); }); it(`${controller.name} supports objects with length`, async () => { const obj = new TestObject(); - obj.set('length', 5); - assert.equal(obj.get('length'), 5); + obj.set("length", 5); + assert.equal(obj.get("length"), 5); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.equalTo('objectId', obj.id); + query.equalTo("objectId", obj.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get('length'), 5); + assert.equal(results[0].get("length"), 5); }); it(`${controller.name} can include User fields`, async () => { - const user = await Parse.User.signUp('bob', 'password', { age: 21 }); + const user = await Parse.User.signUp("bob", "password", { age: 21 }); const obj = new TestObject(); await obj.save({ owner: user }); await obj.pin(); const query = new Parse.Query(TestObject); - query.include('owner'); + query.include("owner"); query.fromLocalDatastore(); const objAgain = await query.get(obj.id); - assert(objAgain.get('owner') instanceof Parse.User); - assert.equal(objAgain.get('owner').get('age'), 21); + assert(objAgain.get("owner") instanceof Parse.User); + 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 () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object('BoxedNumber'); + const obj = new Parse.Object("BoxedNumber"); obj.set({ x: i, orquery: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('orquery', true); - q1.lessThan('x', 2); + 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 q2 = new Parse.Query("BoxedNumber"); + q2.equalTo("orquery", true); + q2.greaterThan("x", 5); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); const results = await orQuery.find(); assert.equal(results.length, 6); results.forEach((number) => { - assert(number.get('x') < 2 || number.get('x') > 5); + assert(number.get("x") < 2 || number.get("x") > 5); }); }); it(`${controller.name} can build complex OR queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object('Child'); - child.set('x', i); - child.set('complexor', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('complexor', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("complexor", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("complexor", true); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('complexor', true); + 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 q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('complexor', true); - q2.lessThan('y', 2); + const q2 = new Parse.Query("Parent"); + q2.equalTo("complexor", true); + q2.lessThan("y", 2); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); - const results = await orQuery.find(); + const results = await orQuery.find(); assert.equal(results.length, 3); }); it(`${controller.name} can build AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object('BoxedNumber'); + const obj = new Parse.Object("BoxedNumber"); obj.set({ x: i, and: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('and', true); - q1.greaterThan('x', 2); + 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 q2 = new Parse.Query("BoxedNumber"); + q2.equalTo("and", true); + q2.lessThan("x", 5); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); const results = await andQuery.find(); assert.equal(results.length, 2); results.forEach((number) => { - assert(number.get('x') > 2 && number.get('x') < 5); + assert(number.get("x") > 2 && number.get("x") < 5); }); }); it(`${controller.name} can build complex AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object('Child'); - child.set('x', i); - child.set('and', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('and', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("and", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("and", true); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('and', true); + 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 q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('and', true); - q2.equalTo('y', 4); + const q2 = new Parse.Query("Parent"); + q2.equalTo("and", true); + q2.equalTo("y", 4); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); @@ -2410,53 +2637,53 @@ function runTest(controller) { it(`${controller.name} can build NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const obj = new Parse.Object('NORTest'); + const obj = new Parse.Object("NORTest"); obj.set({ x: i }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query('NORTest'); - q1.greaterThan('x', 5); - const q2 = new Parse.Query('NORTest'); - q2.lessThan('x', 3); + const q1 = new Parse.Query("NORTest"); + q1.greaterThan("x", 5); + const q2 = new Parse.Query("NORTest"); + q2.lessThan("x", 3); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 3); results.forEach((number) => { - assert(number.get('x') >= 3 && number.get('x') <= 5); + assert(number.get("x") >= 3 && number.get("x") <= 5); }); }); it(`${controller.name} can build complex NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const child = new Parse.Object('Child'); - child.set('x', i); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - const q1 = new Parse.Query('Parent'); - q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('y', 5); + const subQuery = new Parse.Query("Child"); + subQuery.equalTo("x", 4); + const q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); + const q2 = new Parse.Query("Parent"); + q2.equalTo("y", 5); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 8); results.forEach((number) => { - assert(number.get('x') !== 4 || number.get('x') !== 5); + assert(number.get("x") !== 4 || number.get("x") !== 5); }); }); @@ -2470,11 +2697,11 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.fromLocalDatastore(); await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); assert.equal(seen.length, 25); for (let i = 0; i < seen.length; i++) { @@ -2492,16 +2719,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - query.ascending('x'); + query.equalTo("eachtest", true); + query.lessThan("x", 25); + query.ascending("x"); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); @@ -2515,16 +2742,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.limit(20); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); @@ -2538,27 +2765,27 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); + query.equalTo("eachtest", true); + query.lessThan("x", 25); query.skip(20); query.fromLocalDatastore(); try { await query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; }); } catch (e) { - assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); + assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); } }); it(`${controller.name} can select specific keys`, async () => { - const obj = new TestObject({ foo: 'baz', bar: 1 }); + const obj = new TestObject({ foo: "baz", bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); + q.equalTo("objectId", obj.id); + q.select("foo"); q.fromLocalDatastore(); const result = await q.first(); @@ -2566,23 +2793,23 @@ function runTest(controller) { assert(result.createdAt); assert(result.updatedAt); assert(!result.dirty()); - assert.equal(result.get('foo'), 'baz'); - assert.equal(result.get('bar'), undefined); + assert.equal(result.get("foo"), "baz"); + assert.equal(result.get("bar"), undefined); }); it(`${controller.name} can select specific keys with each`, async () => { - const obj = new TestObject({ foo: 'baz', bar: 1 }); + const obj = new TestObject({ foo: "baz", bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); + q.equalTo("objectId", obj.id); + q.select("foo"); q.fromLocalDatastore(); await q.each((o) => { assert(o.id); - assert.equal(o.get('foo'), 'baz'); - assert.equal(o.get('bar'), undefined); + assert.equal(o.get("foo"), "baz"); + assert.equal(o.get("bar"), undefined); }); }); @@ -2593,33 +2820,33 @@ function runTest(controller) { await obj.pin(); let q = new Parse.Query(TestObject); - q.equalTo('dateField', now); + q.equalTo("dateField", now); q.fromLocalDatastore(); let objects = await q.find(); assert.equal(objects.length, 1); const future = new Date(now.getTime() + 1000); q = new Parse.Query(TestObject); - q.lessThan('dateField', future); + q.lessThan("dateField", future); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.lessThanOrEqualTo('dateField', now); + q.lessThanOrEqualTo("dateField", now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); const past = new Date(now.getTime() - 1000); q = new Parse.Query(TestObject); - q.greaterThan('dateField', past); + q.greaterThan("dateField", past); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.greaterThanOrEqualTo('dateField', now); + q.greaterThanOrEqualTo("dateField", now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); @@ -2627,37 +2854,53 @@ 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('name', 'Sacramento'); + sacramento.set("location", new Parse.GeoPoint(38.52, -121.5)); + sacramento.set("name", "Sacramento"); const honolulu = new TestObject(); - honolulu.set('location', new Parse.GeoPoint(21.35, -157.93)); - honolulu.set('name', 'Honolulu'); + honolulu.set("location", new Parse.GeoPoint(21.35, -157.93)); + honolulu.set("name", "Honolulu"); const sf = new TestObject(); - sf.set('location', new Parse.GeoPoint(37.75, -122.68)); - sf.set('name', 'San Francisco'); + sf.set("location", new Parse.GeoPoint(37.75, -122.68)); + sf.set("name", "San Francisco"); await Parse.Object.saveAll([sacramento, honolulu, sf]); await Parse.Object.pinAll([sacramento, honolulu, sf]); 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); + query.withinPolygon("location", points); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); 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); @@ -2672,7 +2915,7 @@ function runTest(controller) { const point = new Parse.GeoPoint(0.5, 0.5); const query = new Parse.Query(TestObject); - query.polygonContains('polygon', point); + query.polygonContains("polygon", point); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); @@ -2681,69 +2924,90 @@ function runTest(controller) { it(`${controller.name} can query from pin subclass`, async () => { class ClassA extends Parse.Object { constructor() { - super('ClassA'); + 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); + Parse.Object.registerSubclass("ClassA", ClassA); class ClassB extends Parse.Object { constructor() { - super('ClassB'); + 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); + Parse.Object.registerSubclass("ClassB", ClassB); const testClassA = new ClassA(); - testClassA.name = 'ABC'; + testClassA.name = "ABC"; await testClassA.pin(); const query = new Parse.Query(ClassA); query.fromLocalDatastore(); - query.equalTo('name', 'ABC'); + query.equalTo("name", "ABC"); const result = await query.first(); - expect(result.get('name')).toBe('ABC'); + expect(result.get("name")).toBe("ABC"); const testClassB = new ClassB(); - testClassB.name = 'XYZ'; + testClassB.name = "XYZ"; testClassB.classA = testClassA; await testClassB.pin(); let localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual(testClassA.toOfflinePointer()); + expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual( + testClassA.toOfflinePointer() + ); await testClassB.save(); expect(testClassB.classA).toBe(testClassA); expect(testClassA.id).toBeDefined(); localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual(testClassA.id); + expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual( + testClassA.id + ); }); }); } -describe('Parse LocalDatastore', () => { +describe("Parse LocalDatastore", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); - Parse.CoreManager.getInstallationController()._setInstallationIdCache('1234'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.CoreManager.getInstallationController()._setInstallationIdCache( + "1234" + ); Parse.enableLocalDatastore(); 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: "Default", file: "../../lib/node/LocalDatastoreController" }, + { + 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..5b150a9e9 100644 --- a/integration/test/ParseMasterKeyTest.js +++ b/integration/test/ParseMasterKeyTest.js @@ -1,46 +1,50 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Master Key', () => { +describe("Master Key", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it('can perform a simple save', (done) => { + it("can perform a simple save", (done) => { const object = new TestObject(); - object.set('color', 'purple'); + object.set("color", "purple"); object.save(null, { useMasterKey: true }).then(() => { assert(object.id); done(); }); }); - 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) => { - Parse.CoreManager.set('MASTER_KEY', null); + 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(() => { // should fail diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 03072ba1e..bd406bd7e 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -1,86 +1,98 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); -const Item = Parse.Object.extend('Item'); -const Container = Parse.Object.extend('Container'); +const TestObject = Parse.Object.extend("TestObject"); +const Item = Parse.Object.extend("Item"); +const Container = Parse.Object.extend("Container"); -describe('Parse Object', () => { +describe("Parse Object", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it('can create objects', (done) => { - const object = new TestObject({ test: 'test' }); + it("can create objects", (done) => { + const object = new TestObject({ test: "test" }); object.save().then((o) => { assert(o); assert(o.id); - assert.equal(o.get('test'), 'test'); + assert.equal(o.get("test"), "test"); 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(); - }); + 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(); + }); }); - 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.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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - it('can check if object exists', async () => { + it("can check if object exists", async () => { const object = new TestObject(); assert.equal(await object.exists(), false); await object.save(); @@ -89,39 +101,45 @@ describe('Parse Object', () => { assert.equal(await object.exists(), false); }); - 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(); - }); + 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(); + }); }); - it('can establish relational fields', (done) => { + it("can establish relational fields", (done) => { const item = new Item(); - item.set('property', 'x'); + 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(); - }); + 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(); + }); }); - 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,89 +151,108 @@ 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'); + 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.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(); + }); }); - 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); + 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); }); - it('does not remove old fields on fetch', (done) => { - const object = new Parse.Object('SimpleObject'); - object.set('foo', 'bar'); - object.set('test', 'foo'); + 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) => { - 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(); - }); + 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(); + }); }); - it('exposes createdAt and updatedAt as top level properties', (done) => { - const object = new TestObject({ foo: 'bar' }); + it("exposes createdAt and updatedAt as top level properties", (done) => { + const object = new TestObject({ foo: "bar" }); object.save().then(() => { assert(object.updatedAt); assert(object.createdAt); @@ -223,9 +260,9 @@ 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' }); + const object = new TestObject({ foo: "bar" }); object.save().then(() => { const end = new Date(); const startDiff = Math.abs(start.getTime() - object.createdAt.getTime()); @@ -238,57 +275,72 @@ describe('Parse Object', () => { }); }); - it('can increment nested fields', async () => { + it("can increment nested fields", async () => { const obj = new TestObject(); - obj.set('objectField', { number: 5 }); - assert.equal(obj.get('objectField').number, 5); + obj.set("objectField", { number: 5 }); + assert.equal(obj.get("objectField").number, 5); await obj.save(); - obj.increment('objectField.number', 15); - assert.equal(obj.get('objectField').number, 20); + obj.increment("objectField.number", 15); + assert.equal(obj.get("objectField").number, 20); await obj.save(); - assert.equal(obj.get('objectField').number, 20); + assert.equal(obj.get("objectField").number, 20); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, 20); + assert.equal(result.get("objectField").number, 20); }); - it('can increment nested field and retain full object', async () => { - const obj = new Parse.Object('TestIncrementObject'); - obj.set('objectField', { number: 5, letter: 'a' }); - assert.equal(obj.get('objectField').number, 5); - assert.equal(obj.get('objectField').letter, 'a'); + it("can increment nested field and retain full object", async () => { + const obj = new Parse.Object("TestIncrementObject"); + obj.set("objectField", { number: 5, letter: "a" }); + 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' }); + obj.increment("objectField.number", 15); + 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'); + assert.equal(obj.get("objectField").number, 20); + assert.equal(obj.get("objectField").letter, "a"); await obj.save(); - assert.equal(obj.get('objectField').number, 20); - assert.equal(obj.get('objectField').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"); + assert.deepStrictEqual(obj.attributes.objectField, { + number: 20, + letter: "a", + }); - const query = new Parse.Query('TestIncrementObject'); + 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.equal(result.get("objectField").number, 20); + assert.equal(result.get("objectField").letter, "a"); + assert.deepStrictEqual(result.attributes.objectField, { + number: 20, + letter: "a", + }); }); - it('can increment non existing field', async () => { + it("can increment non existing field", async () => { const obj = new TestObject(); - obj.set('objectField', { number: 5 }); + obj.set("objectField", { number: 5 }); await obj.save(); - obj.increment('objectField.unknown', 15); - assert.deepEqual(obj.get('objectField'), { + obj.increment("objectField.unknown", 15); + assert.deepEqual(obj.get("objectField"), { number: 5, unknown: 15, }); @@ -296,694 +348,776 @@ describe('Parse Object', () => { const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, 5); - assert.equal(result.get('objectField').unknown, 15); + assert.equal(result.get("objectField").number, 5); + assert.equal(result.get("objectField").unknown, 15); }); - it('can increment nested fields two levels', async () => { + it("can increment nested fields two levels", async () => { const obj = new TestObject(); - obj.set('objectField', { foo: { bar: 5 } }); - assert.equal(obj.get('objectField').foo.bar, 5); + obj.set("objectField", { foo: { bar: 5 } }); + assert.equal(obj.get("objectField").foo.bar, 5); await obj.save(); - obj.increment('objectField.foo.bar', 15); - assert.equal(obj.get('objectField').foo.bar, 20); + obj.increment("objectField.foo.bar", 15); + assert.equal(obj.get("objectField").foo.bar, 20); await obj.save(); - assert.equal(obj.get('objectField').foo.bar, 20); + assert.equal(obj.get("objectField").foo.bar, 20); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').foo.bar, 20); + assert.equal(result.get("objectField").foo.bar, 20); }); - it('can increment nested fields without object', async () => { + it("can increment nested fields without object", async () => { const obj = new TestObject(); - obj.set('hello', 'world'); + obj.set("hello", "world"); await obj.save(); - obj.increment('hello.dot', 15); - try { + obj.increment("hello.dot", 15); + 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" + ); } }); - it('can set nested fields', async () => { + it("can set nested fields", async () => { const obj = new TestObject({ objectField: { number: 5 } }); - assert.equal(obj.get('objectField').number, 5); + assert.equal(obj.get("objectField").number, 5); await obj.save(); - assert.equal(obj.get('objectField').number, 5); - obj.set('objectField.number', 20); - assert.equal(obj.get('objectField').number, 20); + assert.equal(obj.get("objectField").number, 5); + obj.set("objectField.number", 20); + assert.equal(obj.get("objectField").number, 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, 20); + assert.equal(result.get("objectField").number, 20); }); - it('can set non existing fields', async () => { + it("can set non existing fields", async () => { const obj = new TestObject(); - obj.set('objectField', { number: 5 }); + obj.set("objectField", { number: 5 }); await obj.save(); - obj.set('objectField.unknown', 20); + obj.set("objectField.unknown", 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, 5); - assert.equal(result.get('objectField').unknown, 20); + assert.equal(result.get("objectField").number, 5); + assert.equal(result.get("objectField").unknown, 20); }); - it('ignore set nested fields on new object', async () => { + it("ignore set nested fields on new object", async () => { const obj = new TestObject(); - obj.set('objectField.number', 5); + obj.set("objectField.number", 5); assert.deepEqual(obj._getPendingOps()[0], {}); - assert.equal(obj.get('objectField'), undefined); + assert.equal(obj.get("objectField"), undefined); await obj.save(); - assert.equal(obj.get('objectField'), undefined); + assert.equal(obj.get("objectField"), undefined); }); - it('can set nested fields two levels', async () => { + it("can set nested fields two levels", async () => { const obj = new TestObject({ objectField: { foo: { bar: 5 } } }); - assert.equal(obj.get('objectField').foo.bar, 5); + assert.equal(obj.get("objectField").foo.bar, 5); await obj.save(); - assert.equal(obj.get('objectField').foo.bar, 5); - obj.set('objectField.foo.bar', 20); - assert.equal(obj.get('objectField').foo.bar, 20); + assert.equal(obj.get("objectField").foo.bar, 5); + obj.set("objectField.foo.bar", 20); + assert.equal(obj.get("objectField").foo.bar, 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').foo.bar, 20); + assert.equal(result.get("objectField").foo.bar, 20); }); - it('can unset nested fields', async () => { + it("can unset nested fields", async () => { const obj = new TestObject({ objectField: { number: 5, - string: 'hello', - } + string: "hello", + }, }); await obj.save(); - obj.unset('objectField.number'); - assert.equal(obj.get('objectField').number, undefined); - assert.equal(obj.get('objectField').string, 'hello'); + obj.unset("objectField.number"); + assert.equal(obj.get("objectField").number, undefined); + assert.equal(obj.get("objectField").string, "hello"); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, undefined); - assert.equal(result.get('objectField').string, 'hello'); + assert.equal(result.get("objectField").number, undefined); + assert.equal(result.get("objectField").string, "hello"); }); - it('can unset nested fields two levels', async () => { + it("can unset nested fields two levels", async () => { const obj = new TestObject({ objectField: { foo: { bar: 5, }, - string: 'hello', - } + string: "hello", + }, }); await obj.save(); - obj.unset('objectField.foo.bar'); - assert.equal(obj.get('objectField').foo.bar, undefined); - assert.equal(obj.get('objectField').string, 'hello'); + obj.unset("objectField.foo.bar"); + assert.equal(obj.get("objectField").foo.bar, undefined); + assert.equal(obj.get("objectField").string, "hello"); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').foo.bar, undefined); - assert.equal(result.get('objectField').string, 'hello'); + assert.equal(result.get("objectField").foo.bar, undefined); + assert.equal(result.get("objectField").string, "hello"); }); - it('can unset non existing fields', async () => { + it("can unset non existing fields", async () => { const obj = new TestObject(); - obj.set('objectField', { number: 5 }); + obj.set("objectField", { number: 5 }); await obj.save(); - obj.unset('objectField.unknown'); + obj.unset("objectField.unknown"); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get('objectField').number, 5); - assert.equal(result.get('objectField').unknown, undefined); + assert.equal(result.get("objectField").number, 5); + 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.set("foo", null); obj.save().then(() => { - assert.equal(obj.get('foo'), null); + assert.equal(obj.get("foo"), null); done(); }); }); - it('can set boolean fields', (done) => { + it("can set boolean fields", (done) => { const obj = new TestObject(); - obj.set('yes', true); - obj.set('no', false); + obj.set("yes", true); + obj.set("no", false); obj.save().then(() => { - assert.equal(obj.get('yes'), true); - assert.equal(obj.get('no'), false); + assert.equal(obj.get("yes"), true); + assert.equal(obj.get("no"), false); done(); }); }); - 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.set("when", new Date(Date.parse(null))); obj.save().catch(() => { done(); }); }); - it('cannot create invalid class names', (done) => { - const item = new Parse.Object('Foo^Bar'); + 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) => { - const item = new Parse.Object('Item'); - assert(!item.set({ 'foo^bar': 'baz' })); - item.save({ 'foo^bar': 'baz' }).catch((e) => { + 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) => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); }); - 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.get('foobar')); - }); - - 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(); - }); + 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.get("foobar")); + }); + + 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(); + }); }); - it('can delete fields before the first save', (done) => { - const simple = new Parse.Object('SimpleObject'); - simple.set('foo', 'bar'); - simple.unset('foo'); + it("can delete fields before the first save", (done) => { + const simple = new Parse.Object("SimpleObject"); + simple.set("foo", "bar"); + simple.unset("foo"); - assert(!simple.has('foo')); - assert(simple.dirty('foo')); + 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) => { - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - it('can set the object id', () => { + it("can set the object id", () => { const object = new TestObject(); - object.set('objectId', 'foo'); - assert.equal(object.id, 'foo'); - object.set('id', 'bar'); - assert.equal(object.id, 'bar'); + object.set("objectId", "foo"); + assert.equal(object.id, "foo"); + object.set("id", "bar"); + 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'); + object.set("cat", "goog"); + object.set("dog", "bad"); object.save().then(() => { assert(!object.dirty()); - assert(!object.dirty('cat')); - assert(!object.dirty('dog')); + assert(!object.dirty("cat")); + assert(!object.dirty("dog")); - object.set('dog', 'okay'); + object.set("dog", "okay"); assert(object.dirty()); - assert(!object.dirty('cat')); - assert(object.dirty('dog')); + assert(!object.dirty("cat")); + assert(object.dirty("dog")); done(); }); }); - it('can collect dirty keys', (done) => { + it("can collect dirty keys", (done) => { const object = new TestObject(); - object.set('dog', 'good'); - object.set('cat', 'bad'); + object.set("dog", "good"); + object.set("cat", "bad"); assert(object.dirty()); let dirtyKeys = object.dirtyKeys(); assert.equal(dirtyKeys.length, 2); - 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(); - }); - }); - - 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); + 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(); + }); }); - it('can repeatedly unset old attributes', (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) => { 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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.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.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(); + }); }); - 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.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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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) => { - const Parent = Parse.Object.extend('Parent'); - const Child = Parse.Object.extend('Child'); + it("can save children in an array", (done) => { + const Parent = Parse.Object.extend("Parent"); + const Child = Parse.Object.extend("Child"); const child1 = new Child(); const child2 = new Child(); const parent = new Parent(); - child1.set('name', 'jaime'); - child1.set('house', 'lannister'); - child2.set('name', 'cersei'); - 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(); - }); + child1.set("name", "jaime"); + child1.set("house", "lannister"); + child2.set("name", "cersei"); + 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(); + }); }); - it('can skip cascade saving as per request', async(done) => { - const Parent = Parse.Object.extend('Parent'); - const Child = Parse.Object.extend('Child'); + it("can skip cascade saving as per request", async (done) => { + const Parent = Parse.Object.extend("Parent"); + const Child = Parse.Object.extend("Child"); const parent = new Parent(); const child1 = new Child(); const child2 = new Child(); const child3 = new Child(); - child1.set('name', 'rob'); - child2.set('name', 'sansa'); - child3.set('name', 'john'); - parent.set('children', [child1, child2]); - parent.set('bastard', child3); + child1.set("name", "rob"); + child2.set("name", "sansa"); + child3.set("name", "john"); + parent.set("children", [child1, child2]); + parent.set("bastard", child3); expect(parent.save).toThrow(); let results = await new Parse.Query(Child).find(); @@ -993,22 +1127,22 @@ describe('Parse Object', () => { results = await new Parse.Query(Child).find(); assert.equal(results.length, 3); - parent.set('dead', true); - child1.set('dead', true); + parent.set("dead", true); + child1.set("dead", true); await parent.save(null); - const rob = await new Parse.Query(Child).equalTo('name', 'rob').first(); - expect(rob.get('dead')).toBe(true); + const rob = await new Parse.Query(Child).equalTo("name", "rob").first(); + expect(rob.get("dead")).toBe(true); - parent.set('lastname', 'stark'); - child3.set('lastname', 'stark'); + parent.set("lastname", "stark"); + child3.set("lastname", "stark"); await parent.save(null, { cascadeSave: false }); - const john = await new Parse.Query(Child).doesNotExist('lastname').first(); - expect(john.get('lastname')).toBeUndefined(); + const john = await new Parse.Query(Child).doesNotExist("lastname").first(); + expect(john.get("lastname")).toBeUndefined(); 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; @@ -1018,86 +1152,100 @@ describe('Parse Object', () => { return; } - const query = new Parse.Query('TestObject'); - query.equalTo('test', 'doublesave'); + const query = new Parse.Query("TestObject"); + query.equalTo("test", "doublesave"); query.find().then((results) => { assert.equal(results.length, 1); - assert.equal(results[0].get('cat'), 'meow'); - assert.equal(results[0].get('dog'), 'bark'); + 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); + 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.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(); + }); }); - 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) => { - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(() => { + object.save({ foo: "bar" }).then(() => { const json = object.toJSON(); assert(json.foo); assert(json.objectId); @@ -1107,9 +1255,9 @@ describe('Parse Object', () => { }); }); - it('can convert unsaved objects to json', () => { + it("can convert unsaved objects to json", () => { const object = new TestObject(); - object.set({ foo: 'bar' }); + object.set({ foo: "bar" }); const json = object.toJSON(); assert(json.foo); assert(!json.objectId); @@ -1117,145 +1265,167 @@ 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.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(); + }); }); - it('fails validation with a promise', (done) => { - const PickyEater = Parse.Object.extend('PickyEater', { - validate: function(attrs) { - if (attrs.meal === 'tomatoes') { - return 'Ew. Gross.'; + it("fails validation with a promise", (done) => { + const PickyEater = Parse.Object.extend("PickyEater", { + 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.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(); + }); }); - 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'; + o.id = "fakeobject"; Parse.Object.destroyAll([o]).catch((e) => { assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); assert.equal(e.errors.length, 1); @@ -1263,288 +1433,336 @@ describe('Parse Object', () => { }); }); - 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 = []; for (let i = 0; i < numItems; i++) { const item = new Item(); - item.set('x', i); + 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.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(); + }); }); - it('fails fetchAll on multiple classes', () => { + 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); - }); + 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); + }); }); - it('fails fetchAll on unsaved object', () => { + it("fails fetchAll on unsaved object", () => { const unsavedObjectArray = [new TestObject()]; 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++) { const item = new Item(); - item.set('x', i); + 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); - }); - - it('can fetchAllIfNeededWithInclude', async () => { - const pointer = new TestObject({ foo: 'bar' }); - const item1 = new Item({ x: 1}); + 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); + }); + + it("can fetchAllIfNeededWithInclude", async () => { + const pointer = new TestObject({ foo: "bar" }); + const item1 = new Item({ x: 1 }); const item2 = new Item({ x: 2, pointer }); const items = [item1, item2]; await Parse.Object.saveAll(items); const container = new Container(); - container.set('items', items); + container.set("items", items); await container.save(); const query = new Parse.Query(Container); const containerAgain = await query.get(container.id); // Fetch objects with no data - const itemsAgain = containerAgain.get('items'); - const item1Again = itemsAgain[0].set('x', 100); + const itemsAgain = containerAgain.get("items"); + const item1Again = itemsAgain[0].set("x", 100); const item2Again = itemsAgain[1]; // 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 - assert.equal(fetchedItems[1].get('pointer').id, pointer.id); - assert.equal(fetchedItems[1].get('pointer').get('foo'), 'bar'); + assert.equal(fetchedItems[0].get("x"), 1); + assert.equal(fetchedItems[1].get("x"), 2); // item2Again should update + assert.equal(fetchedItems[1].get("pointer").id, pointer.id); + 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 = []; for (let i = 0; i < numItems; i++) { const item = new Item(); - item.set('x', i); + 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) => { assert.equal(e.code, Parse.Error.MISSING_OBJECT_ID); @@ -1552,225 +1770,253 @@ describe('Parse Object', () => { }); }); - it('fails fetchAllIfNeeded on multiple classes', () => { + it("fails fetchAllIfNeeded 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.fetchAllIfNeeded(multiClassArray); - }).catch((e) => { - assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); - }); + 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); + }); }); - it('can rewrite the User classname', (done) => { - assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), true); + 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'); + assert.equal(User1.className, "_User"); Parse.User.allowCustomUserClass(true); - assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), false); + assert.equal(Parse.CoreManager.get("PERFORM_USER_REWRITE"), false); const User2 = Parse.Object.extend({ - className: 'User' + className: "User", }); - assert.equal(User2.className, 'User'); + assert.equal(User2.className, "User"); Parse.User.allowCustomUserClass(false); - assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), true); + assert.equal(Parse.CoreManager.get("PERFORM_USER_REWRITE"), true); 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); - - 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); + user.set("name", "Me"); + 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); - done(); - }); + 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(); - }); + 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(); + }); }); - it('can fetchWithInclude', async () => { + it("can fetchWithInclude", async () => { const parent = new TestObject(); const child = new TestObject(); - child.set('field', 'isChild'); - parent.set('child', child); + child.set("field", "isChild"); + parent.set("child", child); await parent.save(); const obj1 = TestObject.createWithoutData(parent.id); - const fetchedObj1 = await obj1.fetchWithInclude('child'); - assert.equal(obj1.get('child').get('field'), 'isChild'); - assert.equal(fetchedObj1.get('child').get('field'), 'isChild'); + const fetchedObj1 = await obj1.fetchWithInclude("child"); + assert.equal(obj1.get("child").get("field"), "isChild"); + assert.equal(fetchedObj1.get("child").get("field"), "isChild"); const obj2 = TestObject.createWithoutData(parent.id); - const fetchedObj2 = await obj2.fetchWithInclude(['child']); - assert.equal(obj2.get('child').get('field'), 'isChild'); - assert.equal(fetchedObj2.get('child').get('field'), 'isChild'); + const fetchedObj2 = await obj2.fetchWithInclude(["child"]); + assert.equal(obj2.get("child").get("field"), "isChild"); + assert.equal(fetchedObj2.get("child").get("field"), "isChild"); const obj3 = TestObject.createWithoutData(parent.id); - const fetchedObj3 = await obj3.fetchWithInclude([ ['child'] ]); - assert.equal(obj3.get('child').get('field'), 'isChild'); - assert.equal(fetchedObj3.get('child').get('field'), 'isChild'); + const fetchedObj3 = await obj3.fetchWithInclude([["child"]]); + assert.equal(obj3.get("child").get("field"), "isChild"); + assert.equal(fetchedObj3.get("child").get("field"), "isChild"); }); - it('can fetchWithInclude dot notation', async () => { + it("can fetchWithInclude dot notation", async () => { const parent = new TestObject(); const child = new TestObject(); const grandchild = new TestObject(); - grandchild.set('field', 'isGrandchild'); - child.set('grandchild', grandchild); - parent.set('child', child); + grandchild.set("field", "isGrandchild"); + child.set("grandchild", grandchild); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); const obj1 = TestObject.createWithoutData(parent.id); - await obj1.fetchWithInclude('child.grandchild'); - assert.equal(obj1.get('child').get('grandchild').get('field'), 'isGrandchild'); + await obj1.fetchWithInclude("child.grandchild"); + assert.equal( + obj1.get("child").get("grandchild").get("field"), + "isGrandchild" + ); const obj2 = TestObject.createWithoutData(parent.id); - await obj2.fetchWithInclude(['child.grandchild']); - assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); + await obj2.fetchWithInclude(["child.grandchild"]); + assert.equal( + obj2.get("child").get("grandchild").get("field"), + "isGrandchild" + ); const obj3 = TestObject.createWithoutData(parent.id); - await obj3.fetchWithInclude([ ['child.grandchild'] ]); - assert.equal(obj3.get('child').get('grandchild').get('field'), 'isGrandchild'); + await obj3.fetchWithInclude([["child.grandchild"]]); + assert.equal( + obj3.get("child").get("grandchild").get("field"), + "isGrandchild" + ); }); - it('can fetchAllWithInclude', async () => { + it("can fetchAllWithInclude", async () => { const parent = new TestObject(); const child = new TestObject(); - child.set('field', 'isChild'); - parent.set('child', child); + child.set("field", "isChild"); + parent.set("child", child); await parent.save(); const obj1 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj1], 'child'); - assert.equal(obj1.get('child').get('field'), 'isChild'); + await Parse.Object.fetchAllWithInclude([obj1], "child"); + assert.equal(obj1.get("child").get("field"), "isChild"); const obj2 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj2], ['child']); - assert.equal(obj2.get('child').get('field'), 'isChild'); + await Parse.Object.fetchAllWithInclude([obj2], ["child"]); + assert.equal(obj2.get("child").get("field"), "isChild"); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [ ['child'] ]); - assert.equal(obj3.get('child').get('field'), 'isChild'); + await Parse.Object.fetchAllWithInclude([obj3], [["child"]]); + assert.equal(obj3.get("child").get("field"), "isChild"); }); - it('can fetchAllWithInclude dot notation', async () => { + it("can fetchAllWithInclude dot notation", async () => { const parent = new TestObject(); const child = new TestObject(); const grandchild = new TestObject(); - grandchild.set('field', 'isGrandchild'); - child.set('grandchild', grandchild); - parent.set('child', child); + grandchild.set("field", "isGrandchild"); + child.set("grandchild", grandchild); + parent.set("child", child); await Parse.Object.saveAll([parent, child, grandchild]); const obj1 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj1], 'child.grandchild'); - assert.equal(obj1.get('child').get('grandchild').get('field'), 'isGrandchild'); + await Parse.Object.fetchAllWithInclude([obj1], "child.grandchild"); + assert.equal( + obj1.get("child").get("grandchild").get("field"), + "isGrandchild" + ); const obj2 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj2], ['child.grandchild']); - assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); + await Parse.Object.fetchAllWithInclude([obj2], ["child.grandchild"]); + assert.equal( + obj2.get("child").get("grandchild").get("field"), + "isGrandchild" + ); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [ ['child.grandchild'] ]); - assert.equal(obj3.get('child').get('grandchild').get('field'), 'isGrandchild'); + 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) => { - const LimitedObject = Parse.Object.extend('LimitedObject'); - LimitedObject.readOnlyAttributes = function() { - return ['immutable']; + it("fires errors when readonly attributes are changed", (done) => { + const LimitedObject = Parse.Object.extend("LimitedObject"); + LimitedObject.readOnlyAttributes = function () { + return ["immutable"]; }; const lo = new LimitedObject(); try { - lo.set('immutable', 'mutable'); + lo.set("immutable", "mutable"); } catch (e) { done(); } }); - it('fires errors when readonly attributes are unset', (done) => { - const LimitedObject = Parse.Object.extend('LimitedObject'); - LimitedObject.readOnlyAttributes = function() { - return ['immutable']; + it("fires errors when readonly attributes are unset", (done) => { + const LimitedObject = Parse.Object.extend("LimitedObject"); + LimitedObject.readOnlyAttributes = function () { + return ["immutable"]; }; const lo = new LimitedObject(); try { - lo.unset('immutable'); + lo.unset("immutable"); } catch (e) { done(); } }); - 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(); await testObject.save(); - let relation = o.relation('aRelation'); + let relation = o.relation("aRelation"); relation.add(testObject); await o.save(); const o2 = o.clone(); assert.equal( - o.relation('aRelation').targetClassName, - o2.relation('aRelation').targetClassName + o.relation("aRelation").targetClassName, + o2.relation("aRelation").targetClassName ); - let relations = await o.relation('aRelation').query().find(); + let relations = await o.relation("aRelation").query().find(); assert.equal(relations.length, 1); - relations = await o2.relation('aRelation').query().find(); + relations = await o2.relation("aRelation").query().find(); assert.equal(relations.length, 0); - relation = o2.relation('aRelation'); + relation = o2.relation("aRelation"); relation.add(testObject); await o2.save(); - relations = await o.relation('aRelation').query().find(); + relations = await o.relation("aRelation").query().find(); assert.equal(relations.length, 1); - relations = await o2.relation('aRelation').query().find(); + relations = await o2.relation("aRelation").query().find(); assert.equal(relations.length, 1); done(); }); - it('isDataAvailable', async () => { - const child = new TestObject({ foo: 'bar' }); + it("isDataAvailable", async () => { + const child = new TestObject({ foo: "bar" }); assert.equal(child.isDataAvailable(), false); const parent = new TestObject({ child }); @@ -1781,20 +2027,20 @@ describe('Parse Object', () => { const query = new Parse.Query(TestObject); const fetched = await query.get(parent.id); - const unfetched = fetched.get('child'); + const unfetched = fetched.get("child"); assert.equal(fetched.isDataAvailable(), true); assert.equal(unfetched.isDataAvailable(), false); }); - it('isDataAvailable user', async () => { + it("isDataAvailable user", async () => { let user = new Parse.User(); - user.set('username', 'plain'); - user.set('password', 'plain'); + user.set("username", "plain"); + user.set("password", "plain"); await user.signUp(); assert.equal(user.isDataAvailable(), true); - user = await Parse.User.logIn('plain', 'plain'); + user = await Parse.User.logIn("plain", "plain"); assert.equal(user.isDataAvailable(), true); const query = new Parse.Query(Parse.User); diff --git a/integration/test/ParsePolygonTest.js b/integration/test/ParsePolygonTest.js index 38b4de4e9..564ab5712 100644 --- a/integration/test/ParsePolygonTest.js +++ b/integration/test/ParsePolygonTest.js @@ -1,13 +1,13 @@ -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Polygon', () => { +describe("Polygon", () => { beforeAll(() => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); }); @@ -17,56 +17,81 @@ describe('Polygon', () => { }); }); - 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,16 +107,21 @@ describe('Polygon', () => { } }); - it('fail save with invalid array', (done) => { + it("fail save with invalid array", (done) => { try { - new Parse.Polygon([['str1'], ['str2'], ['str3']]); + new Parse.Polygon([["str1"], ["str2"], ["str3"]]); } catch (e) { done(); } }); - 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..2b80b7679 100644 --- a/integration/test/ParseQueryAggregateTest.js +++ b/integration/test/ParseQueryAggregateTest.js @@ -1,31 +1,40 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Parse Aggregate Query', () => { +describe("Parse Aggregate Query", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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' }, + group: { objectId: "$name" }, }; const query = new Parse.Query(TestObject); query.aggregate(pipeline).then((results) => { @@ -34,10 +43,8 @@ describe('Parse Aggregate Query', () => { }); }); - 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) => { assert.equal(results.length, 3); @@ -45,7 +52,7 @@ describe('Parse Aggregate Query', () => { }); }); - it('aggregate pipeline invalid query', (done) => { + it("aggregate pipeline invalid query", (done) => { const pipeline = 1234; const query = new Parse.Query(TestObject); try { @@ -55,39 +62,52 @@ describe('Parse Aggregate Query', () => { } }); - it('aggregate allow multiple of same stage', async () => { + it("aggregate allow multiple of same stage", async () => { const pointer1 = new TestObject({ value: 1 }); const pointer2 = new TestObject({ value: 2 }); const pointer3 = new TestObject({ value: 3 }); - const obj1 = new TestObject({ pointer: pointer1, name: 'Hello' }); - const obj2 = new TestObject({ pointer: pointer2, name: 'Hello' }); - const obj3 = new TestObject({ pointer: pointer3, name: 'World' }); + const obj1 = new TestObject({ pointer: pointer1, name: "Hello" }); + 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 }, - }]; - await Parse.Object.saveAll([pointer1, pointer2, pointer3, obj1, obj2, obj3]); + { + // 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); const results = await query.aggregate(pipeline); @@ -96,18 +116,18 @@ describe('Parse Aggregate Query', () => { expect(results[0].tempPointer.value).toEqual(2); }); - it('aggregate pipeline on top of a simple query', async done => { + it("aggregate pipeline on top of a simple query", async (done) => { const pipeline = { - group: { objectId: '$name' }, + group: { objectId: "$name" }, }; let results = await new Parse.Query(TestObject) - .equalTo('name', 'foo') + .equalTo("name", "foo") .aggregate(pipeline); expect(results.length).toBe(1); results = await new Parse.Query(TestObject) - .equalTo('score', 20) + .equalTo("score", 20) .aggregate(pipeline); expect(results.length).toBe(1); @@ -115,9 +135,9 @@ describe('Parse Aggregate Query', () => { done(); }); - it('distinct 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 +146,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..b9d54c8b0 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -1,58 +1,74 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Parse Query', () => { +describe("Parse Query", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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() }); - }); - - - 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(); - }); + 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 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); + 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(); + }); }); - it('can do query with count', async () => { + 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); + }); + + it("can do query with count", async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: true })); @@ -61,17 +77,17 @@ 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(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"); } }); - it('can do query withCount set to false', async () => { + it("can do query withCount set to false", async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: true })); @@ -84,151 +100,160 @@ 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 () => { + 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(typeof count == "number"); assert.equal(results.length, 0); assert.equal(count, 0); }); - it('can do query with count and limit', async () => { + 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(typeof count == "number"); assert.equal(results.length, 2); assert.equal(count, 4); }); - it('can do query withCount and skip', async () => { + 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(typeof count == "number"); assert.equal(results.length, 1); assert.equal(count, 4); }); - it('can do query when withCount set without arguments', async () => { + 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(typeof count == "number"); assert.equal(results.length, 4); assert.equal(count, 4); }); - it('can do query when withCount undefined', async () => { + 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(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'); + const message = new Parse.Object("Message"); if (i > 0) { - message.set('prior', messageList[i - 1]); + message.set("prior", messageList[i - 1]); } 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) => { - const NumberSet = Parse.Object.extend('NumberSet'); + 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) => { - const StringSet = Parse.Object.extend('StringSet'); + 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(); - }); + 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(); + }); }); - it('can do containsAll queries with dates', (done) => { - const DateSet = Parse.Object.extend('DateSet'); + 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; @@ -247,67 +272,78 @@ describe('Parse Query', () => { function makeDates(stringArray) { return stringArray.map((date) => { - return parseDate(date + 'T00:00:00Z'); + 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) => { - const MessageSet = Parse.Object.extend('MessageSet'); + 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 () => { - const NumberSet = Parse.Object.extend('NumberSet'); + it("can do containedBy queries with numbers", async () => { + const NumberSet = Parse.Object.extend("NumberSet"); const objectsList = []; objectsList.push(new NumberSet({ numbers: [0, 1, 2] })); objectsList.push(new NumberSet({ numbers: [2, 0] })); @@ -316,54 +352,54 @@ describe('Parse Query', () => { await Parse.Object.saveAll(objectsList); const query = new Parse.Query(NumberSet); - query.containedBy('numbers', [1, 2, 3, 4, 5]); + query.containedBy("numbers", [1, 2, 3, 4, 5]); const results = await query.find(); assert.equal(results.length, 1); }); - it('can do containedBy queries with pointer', async () => { + it("can do containedBy queries with pointer", async () => { const objects = Array.from(Array(10).keys()).map((idx) => { - const obj = new Parse.Object('Object'); - obj.set('key', idx); + const obj = new Parse.Object("Object"); + obj.set("key", idx); return obj; }); - const parent1 = new Parse.Object('Parent'); - const parent2 = new Parse.Object('Parent'); - const parent3 = new Parse.Object('Parent'); + const parent1 = new Parse.Object("Parent"); + const parent2 = new Parse.Object("Parent"); + const parent3 = new Parse.Object("Parent"); await Parse.Object.saveAll(objects); // [0, 1, 2] - parent1.set('objects', objects.slice(0, 3)); + parent1.set("objects", objects.slice(0, 3)); const shift = objects.shift(); // [2, 0] - parent2.set('objects', [objects[1], shift]); + parent2.set("objects", [objects[1], shift]); // [1, 2, 3, 4] - parent3.set('objects', objects.slice(1, 4)); + parent3.set("objects", objects.slice(1, 4)); await Parse.Object.saveAll([parent1, parent2, parent3]); - const query = new Parse.Query('Parent'); - query.containedBy('objects', objects); + const query = new Parse.Query("Parent"); + query.containedBy("objects", objects); const results = await query.find(); assert.equal(results.length, 1); assert.equal(results[0].id, parent3.id); }); - it('can do equalTo queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 3); + it("can do equalTo queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 3); query.find().then((results) => { assert.equal(results.length, 1); done(); }); }); - it('can do equalTo queries with object', (done) => { - const query = new Parse.Query('BoxedNumber'); + it("can do equalTo queries with object", (done) => { + const query = new Parse.Query("BoxedNumber"); query.equalTo({ number: 3 }); query.find().then((results) => { assert.equal(results.length, 1); @@ -371,82 +407,82 @@ describe('Parse Query', () => { }); }); - it('can test equality with undefined', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', undefined); + it("can test equality with undefined", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", undefined); query.find().then((results) => { assert.equal(results.length, 0); done(); }); }); - it('can perform lessThan queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 7); + it("can perform lessThan queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.lessThan("number", 7); query.find().then((results) => { assert.equal(results.length, 7); done(); }); }); - it('can perform lessThanOrEqualTo queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); + it("can perform lessThanOrEqualTo queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.lessThanOrEqualTo("number", 7); query.find().then((results) => { assert.equal(results.length, 8); done(); }); }); - it('can perform greaterThan queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 7); + it("can perform greaterThan queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.greaterThan("number", 7); query.find().then((results) => { assert.equal(results.length, 2); done(); }); }); - it('can perform greaterThanOrEqualTo queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThanOrEqualTo('number', 7); + it("can perform greaterThanOrEqualTo queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.greaterThanOrEqualTo("number", 7); query.find().then((results) => { assert.equal(results.length, 3); done(); }); }); - it('can combine lessThanOrEqualTo and greaterThanOrEqualTo queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.lessThanOrEqualTo('number', 7); - query.greaterThanOrEqualTo('number', 7); + 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) => { assert.equal(results.length, 1); done(); }); }); - it('can combine lessThan and greaterThan queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.lessThan('number', 9); - query.greaterThan('number', 3); + 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) => { assert.equal(results.length, 5); done(); }); }); - it('can perform notEqualTo queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.notEqualTo('number', 5); + it("can perform notEqualTo queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.notEqualTo("number", 5); query.find().then((results) => { assert.equal(results.length, 9); done(); }); }); - it('can perform notEqualTo queries with object', (done) => { - const query = new Parse.Query('BoxedNumber'); + it("can perform notEqualTo queries with object", (done) => { + const query = new Parse.Query("BoxedNumber"); query.notEqualTo({ number: 5 }); query.find().then((results) => { assert.equal(results.length, 9); @@ -454,829 +490,1008 @@ describe('Parse Query', () => { }); }); - it('can perform containedIn queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.containedIn('number', [3,5,7,9,11]); + it("can perform containedIn queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.containedIn("number", [3, 5, 7, 9, 11]); query.find().then((results) => { assert.equal(results.length, 4); done(); }); }); - it('can perform notContainedIn queries', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.notContainedIn('number', [3,5,7,9,11]); + it("can perform notContainedIn queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + 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) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 15); + it("can find no elements", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 15); query.find().then((results) => { assert.equal(results.length, 0); done(); }); }); - it('handles when find throws errors', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + it("handles when find throws errors", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); 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) => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('number'); + it("can query for the first result", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.ascending("number"); query.first().then((result) => { - assert.equal(result.get('number'), 0); + assert.equal(result.get("number"), 0); done(); }); }); - it('can query for the first with no results', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('number', 20); + it("can query for the first with no results", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("number", 20); 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) => { - const query = new Parse.Query('BoxedNumber'); - query.equalTo('$foo', 'bar'); + it("handles when first throws errors", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.equalTo("$foo", "bar"); 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) => { - const query = new Parse.Query('BoxedNumber'); - query.greaterThan('number', 1); + it("can perform count queries", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.greaterThan("number", 1); query.count().then((count) => { assert.equal(count, 8); done(); }); }); - it('can order by ascending numbers', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('number'); + it("can order by ascending numbers", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.ascending("number"); query.find().then((results) => { - assert.equal(results[0].get('number'), 0); - assert.equal(results[9].get('number'), 9); + assert.equal(results[0].get("number"), 0); + assert.equal(results[9].get("number"), 9); done(); }); }); - it('can order by descending numbers', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.descending('number'); + it("can order by descending numbers", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.descending("number"); query.find().then((results) => { - assert.equal(results[0].get('number'), 9); - assert.equal(results[9].get('number'), 0); + 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - it('can not order by password', (done) => { - const query = new Parse.Query('BoxedNumber'); - query.ascending('_password'); + it("can not order by password", (done) => { + const query = new Parse.Query("BoxedNumber"); + query.ascending("_password"); 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'); + 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(); - }); + 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(); + }); }); - 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.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(); + }); }); - 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.matches("myString", "football", "some invalid thing"); 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.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(); + }); }); - 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.set("website", "\n\nbuffer\n\nparse.COM"); + 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(); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } 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 }); if (i % 2) { - item.set('y', i + 1); + item.set("y", i + 1); } else { - item.set('z', i + 1); + item.set("z", i + 1); } 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); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } 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 }); + const container = new Parse.Object("Container", { relation_dne: true }); if (i % 2) { - container.set('y', i); + container.set("y", i); } else { const item = new TestObject(); - item.set('x', i); - container.set('x', item); + item.set("x", i); + container.set("x", item); objects.push(item); } 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) => { + 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) => { 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(); - }); + 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(); + }); }); - it('can includeAll nested objects', async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + it("can includeAll nested objects", async () => { + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - assert.equal(parentAgain.get('child1').get('foo'), 'bar'); - assert.equal(parentAgain.get('child2').get('foo'), 'baz'); - assert.equal(parentAgain.get('child3').get('foo'), 'bin'); - }); - - it('can includeAll nested objects in .each', async () => { - const child1 = new TestObject({ foo: 'bar' }); - const child2 = new TestObject({ foo: 'baz' }); - const child3 = new TestObject({ foo: 'bin' }); - const parent = new Parse.Object('Container'); - parent.set('child1', child1); - parent.set('child2', child2); - parent.set('child3', child3); + assert.equal(parentAgain.get("child1").get("foo"), "bar"); + assert.equal(parentAgain.get("child2").get("foo"), "baz"); + assert.equal(parentAgain.get("child3").get("foo"), "bin"); + }); + + it("can includeAll nested objects in .each", async () => { + const child1 = new TestObject({ foo: "bar" }); + const child2 = new TestObject({ foo: "baz" }); + const child3 = new TestObject({ foo: "bin" }); + const parent = new Parse.Object("Container"); + parent.set("child1", child1); + parent.set("child2", child2); + parent.set("child3", child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); + const query = new Parse.Query("Container"); + query.equalTo("objectId", parent.id); query.includeAll(); 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'); + assert.equal(obj.get("child1").get("foo"), "bar"); + assert.equal(obj.get("child2").get("foo"), "baz"); + assert.equal(obj.get("child3").get("foo"), "bin"); }); }); - it('can return all objects with findAll', async () => { - const objs = [...Array(101)].map(() => new Parse.Object('Container')); + it("can return all objects with findAll", async () => { + const objs = [...Array(101)].map(() => new Parse.Object("Container")); await Parse.Object.saveAll(objs); - const query = new Parse.Query('Container'); + const query = new Parse.Query("Container"); const result = await query.findAll(); 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(); - }); + 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(); + }); }); - 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'); + 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"); const objects = []; for (let i = 0; i < 5; i++) { @@ -1286,7 +1501,7 @@ describe('Parse Query', () => { parent: new Parent({ y: i, child: new Child({ - x: i + x: i, }), }), }); @@ -1294,694 +1509,770 @@ 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) => { - 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(); - }); + 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(); + }); }); - it('can exclude keys', async () => { + it("can exclude keys", async () => { const object = new TestObject({ - hello: 'world', - foo: 'bar', - slice: 'pizza', + hello: "world", + foo: "bar", + slice: "pizza", }); await object.save(); const query = new Parse.Query(TestObject); - query.exclude('foo'); + query.exclude("foo"); const result = await query.get(object.id); - assert.equal(result.get('foo'), undefined); - assert.equal(result.get('hello'), 'world'); - assert.equal(result.get('slice'), 'pizza'); + assert.equal(result.get("foo"), undefined); + assert.equal(result.get("hello"), "world"); + assert.equal(result.get("slice"), "pizza"); }); - it('can exclude multiple keys', async () => { + it("can exclude multiple keys", async () => { const object = new TestObject({ - hello: 'world', - foo: 'bar', - slice: 'pizza', + hello: "world", + foo: "bar", + slice: "pizza", }); await object.save(); const query = new Parse.Query(TestObject); - query.exclude(['foo', 'hello']); + query.exclude(["foo", "hello"]); const result = await query.get(object.id); - assert.equal(result.get('foo'), undefined); - assert.equal(result.get('hello'), undefined); - assert.equal(result.get('slice'), 'pizza'); + assert.equal(result.get("foo"), undefined); + assert.equal(result.get("hello"), undefined); + assert.equal(result.get("slice"), "pizza"); }); - it('uses subclasses when creating objects', (done) => { - const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); - let ChildObject = Parse.Object.extend('ChildObject', { + it("uses subclasses when creating objects", (done) => { + const ParentObject = Parse.Object.extend({ className: "ParentObject" }); + let ChildObject = Parse.Object.extend("ChildObject", { foo() { - return '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'; - } + parent.set("child", child); + 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) => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const ParentObject = Parse.Object.extend('ParentObject'); - const ChildObject = Parse.Object.extend('ChildObject'); + 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(); - }) - .catch(err => { + 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) => { - const Restaurant = Parse.Object.extend('Restaurant'); - const Person = Parse.Object.extend('Person'); + it("can select keys from a matched query", (done) => { + const Restaurant = Parse.Object.extend("Restaurant"); + const Person = Parse.Object.extend("Person"); const objects = [ - new Restaurant({ rating: 5, location: 'Djibouti' }), - new Restaurant({ rating: 3, location: 'Ouagadougou' }), - new Person({ name: 'Bob', hometown: 'Djibouti' }), - new Person({ name: 'Tom', hometown: 'Ouagadougou' }), - new Person({ name: 'Billy', hometown: 'Detroit' }), + new Restaurant({ rating: 5, location: "Djibouti" }), + new Restaurant({ rating: 3, location: "Ouagadougou" }), + new Person({ name: "Bob", hometown: "Djibouti" }), + new Person({ name: "Tom", hometown: "Ouagadougou" }), + 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.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(); + }); }); - 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'); + 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'); - child.set('x', i); - child.set('complexor', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('complexor', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("complexor", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("complexor", true); + 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'); + 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'); - child.set('x', i); - child.set('and', true); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('and', true); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + child.set("and", true); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("and", true); + 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); - }); - - it('can build NOR queries', async () => { + 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 () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const obj = new Parse.Object('NORTest'); + const obj = new Parse.Object("NORTest"); obj.set({ x: i }); objects.push(obj); } await Parse.Object.saveAll(objects); - const q1 = new Parse.Query('NORTest'); - q1.greaterThan('x', 5); - const q2 = new Parse.Query('NORTest'); - q2.lessThan('x', 3); + const q1 = new Parse.Query("NORTest"); + q1.greaterThan("x", 5); + const q2 = new Parse.Query("NORTest"); + q2.lessThan("x", 3); const norQuery = Parse.Query.nor(q1, q2); const results = await norQuery.find(); assert.equal(results.length, 3); results.forEach((number) => { - assert(number.get('x') >= 3 && number.get('x') <= 5); + assert(number.get("x") >= 3 && number.get("x") <= 5); }); }); - it('can build complex NOR queries', async () => { + it("can build complex NOR queries", async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const child = new Parse.Object('Child'); - child.set('x', i); - const parent = new Parse.Object('Parent'); - parent.set('child', child); - parent.set('y', i); + const child = new Parse.Object("Child"); + child.set("x", i); + const parent = new Parse.Object("Parent"); + parent.set("child", child); + parent.set("y", i); objects.push(parent); } await Parse.Object.saveAll(objects); - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - const q1 = new Parse.Query('Parent'); - q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('y', 5); + const subQuery = new Parse.Query("Child"); + subQuery.equalTo("x", 4); + const q1 = new Parse.Query("Parent"); + q1.matchesQuery("child", subQuery); + const q2 = new Parse.Query("Parent"); + q2.equalTo("y", 5); const norQuery = Parse.Query.nor(q1, q2); const results = await norQuery.find(); assert.equal(results.length, 8); results.forEach((number) => { - assert(number.get('x') !== 4 || number.get('x') !== 5); + 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) => { - 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(); - }); + 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(); + }); }); - 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); + 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); + }); + }) + .then(() => { + done(); }); - }).then(() => { - done(); - }); }); - it('can perform a full text search', () => { + it("can perform a full text search", () => { const subjects = [ - 'coffee', - 'Coffee Shopping', - 'Baking a cake', - 'baking', - 'Café Con Leche', - 'Сырники', - 'coffee and cream', - 'Cafe con Leche', + "coffee", + "Coffee Shopping", + "Baking a cake", + "baking", + "Café Con Leche", + "Сырники", + "coffee and cream", + "Cafe con Leche", ]; const objects = []; for (const i in subjects) { 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', () => { + it("can perform a full text search sort", () => { const subjects = [ - 'coffee', - 'Coffee Shopping', - 'Baking a cake', - 'baking', - 'Café Con Leche', - 'Сырники', - 'coffee and cream', - 'Cafe con Leche', + "coffee", + "Coffee Shopping", + "Baking a cake", + "baking", + "Café Con Leche", + "Сырники", + "coffee and cream", + "Cafe con Leche", ]; const objects = []; for (const i in subjects) { 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', () => { + it("can perform a full text search with language options", () => { const subjects = [ - 'café', - 'loja de café', - 'preparando um café', - 'preparar', - 'café com leite', - 'Сырники', - 'prepare café e creme', - 'preparação de cafe com leite', + "café", + "loja de café", + "preparando um café", + "preparar", + "café com leite", + "Сырники", + "prepare café e creme", + "preparação de cafe com leite", ]; - const TestLanguageOption = Parse.Object.extend('TestLanguageOption'); + const TestLanguageOption = Parse.Object.extend("TestLanguageOption"); const objects = []; for (const i in subjects) { 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', () => { + it("can perform a full text search with case sensitive options", () => { const subjects = [ - 'café', - 'loja de café', - 'Preparando um café', - 'preparar', - 'café com leite', - 'Сырники', - 'Preparar café e creme', - 'preparação de cafe com leite', + "café", + "loja de café", + "Preparando um café", + "preparar", + "café com leite", + "Сырники", + "Preparar café e creme", + "preparação de cafe com leite", ]; - const TestCaseOption = Parse.Object.extend('TestCaseOption'); + const TestCaseOption = Parse.Object.extend("TestCaseOption"); const objects = []; for (const i in subjects) { 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', () => { + it("can perform a full text search with diacritic sensitive options", () => { const subjects = [ - 'café', - 'loja de café', - 'preparando um café', - 'Preparar', - 'café com leite', - 'Сырники', - 'preparar café e creme', - 'preparação de cafe com leite', + "café", + "loja de café", + "preparando um café", + "Preparar", + "café com leite", + "Сырники", + "preparar café e creme", + "preparação de cafe com leite", ]; - const TestDiacriticOption = Parse.Object.extend('TestDiacriticOption'); + const TestDiacriticOption = Parse.Object.extend("TestDiacriticOption"); const objects = []; for (const i in subjects) { 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', () => { + 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', + "Café", + "café", + "preparar Cafe e creme", + "preparação de cafe com leite", ]; - const TestCaseDiacriticOption = Parse.Object.extend('TestCaseDiacriticOption'); + 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é', - 'preparando um café', - 'preparar', - 'café com leite', - 'Сырники', - 'prepare café e creme', - 'preparação de cafe com leite', + "café", + "loja de café", + "preparando um café", + "preparar", + "café com leite", + "Сырники", + "prepare café e creme", + "preparação de cafe com leite", ]; const objects = []; for (const i in subjects) { 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 () => { - const obj1 = new TestObject({ foo: 'bar' }); - const obj2 = new TestObject({ foo: 'baz' }); - const obj3 = new TestObject({ foo: 'bin' }); + it("can return results in map", async () => { + const obj1 = new TestObject({ foo: "bar" }); + const obj2 = new TestObject({ foo: "baz" }); + const obj3 = new TestObject({ foo: "bin" }); await Parse.Object.saveAll([obj1, obj2, obj3]); let i = 0; const mapQuery = new Parse.Query(TestObject); @@ -1989,18 +2280,18 @@ describe('Parse Query', () => { assert.equal(index, i); assert.equal(query, mapQuery); i += 1; - return object.get('foo'); + return object.get("foo"); }); - assert.equal(results.includes('bar'), true); - assert.equal(results.includes('baz'), true); - assert.equal(results.includes('bin'), true); + assert.equal(results.includes("bar"), true); + assert.equal(results.includes("baz"), true); + assert.equal(results.includes("bin"), true); assert.equal(results.length, 3); }); - it('can return results in filter', async () => { - const obj1 = new TestObject({ foo: 'bar' }); - const obj2 = new TestObject({ foo: 'baz' }); - const obj3 = new TestObject({ foo: 'bin' }); + it("can return results in filter", async () => { + const obj1 = new TestObject({ foo: "bar" }); + const obj2 = new TestObject({ foo: "baz" }); + const obj3 = new TestObject({ foo: "bin" }); await Parse.Object.saveAll([obj1, obj2, obj3]); let i = 0; const filterQuery = new Parse.Query(TestObject); @@ -2008,13 +2299,13 @@ describe('Parse Query', () => { assert.equal(index, i); assert.equal(query, filterQuery); i += 1; - return object.get('foo') === 'bar'; + return object.get("foo") === "bar"; }); - assert.equal(results[0].get('foo'), 'bar'); + assert.equal(results[0].get("foo"), "bar"); assert.equal(results.length, 1); }); - it('can return results in reduce', async () => { + it("can return results in reduce", async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); @@ -2024,12 +2315,12 @@ describe('Parse Query', () => { const result = await reduceQuery.reduce((accumulator, object, index) => { assert.equal(index, i); i += 1; - return accumulator + object.get('number'); + return accumulator + object.get("number"); }, 0); assert.equal(result, 6); }); - it('can cancel query', async () => { + it("can cancel query", async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); @@ -2042,31 +2333,34 @@ describe('Parse Query', () => { query.cancel(); }); - it('can query with hint', async () => { + it("can query with hint", async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); await Parse.Object.saveAll([obj1, obj2, obj3]); const query = new Parse.Query(TestObject); - query.hint('_id_'); + query.hint("_id_"); query.explain(); const explain = await query.find(); - assert.equal(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName, '_id_'); + assert.equal( + explain.queryPlanner.winningPlan.inputStage.inputStage.indexName, + "_id_" + ); }); - it('can query with select on null field', async () => { + it("can query with select on null field", async () => { const obj1 = new TestObject({ number: 1, arrayField: [] }); const obj2 = new TestObject({ number: 2, arrayField: [{ subfield: 1 }] }); const obj3 = new TestObject({ number: 3, arrayField: null }); await Parse.Object.saveAll([obj1, obj2, obj3]); const query = new Parse.Query(TestObject); - query.select(['arrayField.subfield']); - query.ascending('number'); + query.select(["arrayField.subfield"]); + query.ascending("number"); const results = await query.find(); - expect(results[0].get('arrayField')).toEqual([]); - expect(results[1].get('arrayField')).toEqual([{ subfield: 1 }]); - expect(results[2].get('arrayField')).toEqual(null); + expect(results[0].get("arrayField")).toEqual([]); + expect(results[1].get("arrayField")).toEqual([{ subfield: 1 }]); + expect(results[2].get("arrayField")).toEqual(null); }); }); diff --git a/integration/test/ParseRelationTest.js b/integration/test/ParseRelationTest.js index 9c1915d11..57c76e65a 100644 --- a/integration/test/ParseRelationTest.js +++ b/integration/test/ParseRelationTest.js @@ -1,248 +1,275 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Parse Relation', () => { +describe("Parse Relation", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it('can do a simple add and remove', (done) => { - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const ChildObject = Parse.Object.extend('ChildObject'); + 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) => { - const Wheel = Parse.Object.extend('Wheel'); - const Car = Parse.Object.extend('Car'); + 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) => { - const Wheel = Parse.Object.extend('Wheel'); - const Car = Parse.Object.extend('Car'); + 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 () => { + it("can add empty array to relation", async () => { const object1 = new TestObject(); await object1.save(); const object2 = new TestObject(); - object2.relation('related').add(object1); + object2.relation("related").add(object1); await object2.save(); - object2.relation('related').add([]); + object2.relation("related").add([]); await object2.save(); - const relation = object2.relation('related'); + const relation = object2.relation("related"); const query = relation.query(); const results = await query.find(); expect(results.length).toBe(1); }); - it('can remove empty array from relation', async () => { + it("can remove empty array from relation", async () => { const object1 = new TestObject(); await object1.save(); const object2 = new TestObject(); - object2.relation('related').add(object1); + object2.relation("related").add(object1); await object2.save(); - object2.relation('related').remove([]); + object2.relation("related").remove([]); await object2.save(); - const relation = object2.relation('related'); + const relation = object2.relation("related"); const query = relation.query(); const results = await query.find(); expect(results.length).toBe(1); diff --git a/integration/test/ParseRoleTest.js b/integration/test/ParseRoleTest.js index d5174a3e4..61aa72c4a 100644 --- a/integration/test/ParseRoleTest.js +++ b/integration/test/ParseRoleTest.js @@ -1,11 +1,11 @@ -'use strict'; +"use strict"; /* eslint-disable no-unused-vars */ -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); function privateTo(someone) { const acl = new Parse.ACL(); @@ -23,12 +23,12 @@ function publicAccess() { function createUser(username) { const user = new Parse.User(); - user.set('username', username); - user.set('password', username); + user.set("username", username); + user.set("password", username); return user; } -describe('Parse Role', () => { +describe("Parse Role", () => { /** TODO: Implement these. There was some bugginess related to parse-server. **/ }); diff --git a/integration/test/ParseSchemaTest.js b/integration/test/ParseSchemaTest.js index ab07e95f9..49e824b8e 100644 --- a/integration/test/ParseSchemaTest.js +++ b/integration/test/ParseSchemaTest.js @@ -1,6 +1,6 @@ -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); const emptyCLPS = { find: {}, @@ -14,23 +14,23 @@ const emptyCLPS = { }; const defaultCLPS = { - find: { '*': true }, - count: { '*': true }, - get: { '*': true }, - create: { '*': true }, - update: { '*': true }, - delete: { '*': true }, - addField: { '*': true }, - protectedFields: { '*': [] }, + find: { "*": true }, + count: { "*": true }, + get: { "*": true }, + create: { "*": true }, + update: { "*": true }, + delete: { "*": true }, + addField: { "*": true }, + protectedFields: { "*": [] }, }; -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); -describe('Schema', () => { +describe("Schema", () => { beforeAll(() => { - Parse.initialize('integration'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); - Parse.CoreManager.set('MASTER_KEY', 'notsosecret'); + Parse.initialize("integration"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.CoreManager.set("MASTER_KEY", "notsosecret"); Parse.Storage._clear(); }); @@ -38,138 +38,207 @@ describe('Schema', () => { 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) => { - const testSchema = new Parse.Schema('SchemaTest'); - testSchema.get().then(() => {}).catch(() => { - done(); - }); + it("invalid get no schema", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); + testSchema + .get() + .then(() => {}) + .catch(() => { + done(); + }); }); - it('save', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("save", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); testSchema.save().then((result) => { - assert.equal(result.className, 'SchemaTest'); + assert.equal(result.className, "SchemaTest"); done(); }); }); - it('get', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("get", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); testSchema - .addField('defaultFieldString') - .addString('stringField') - .addNumber('numberField') - .addBoolean('booleanField') - .addDate('dateField') - .addFile('fileField') - .addGeoPoint('geoPointField') - .addPolygon('polygonField') - .addArray('arrayField') - .addObject('objectField') - .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(); - }); + .addField("defaultFieldString") + .addString("stringField") + .addNumber("numberField") + .addBoolean("booleanField") + .addDate("dateField") + .addFile("fileField") + .addGeoPoint("geoPointField") + .addPolygon("polygonField") + .addArray("arrayField") + .addObject("objectField") + .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(); + }); }); - it('all', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then(() => { - return Parse.Schema.all(); - }).then((results) => { - assert.equal(results.length, 1); - 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(); + }); }); - it('save required and default values', async () => { - const testSchema = new Parse.Schema('SchemaTest'); - testSchema.addField('fieldString', 'String', { required: true, defaultValue: 'Hello World' }); + it("save required and default values", async () => { + const testSchema = new Parse.Schema("SchemaTest"); + 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' - }) - const object = new Parse.Object('SchemaTest'); + type: "String", + required: true, + defaultValue: "Hello World", + }); + const object = new Parse.Object("SchemaTest"); await object.save(); - assert.equal(object.get('fieldString'), 'Hello World'); + assert.equal(object.get("fieldString"), "Hello World"); }); - it('save required and default pointer values', async () => { + it("save required and default pointer values", async () => { const pointer = new TestObject(); await pointer.save(); - const testSchema = new Parse.Schema('SchemaTest'); + 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()); + assert.deepEqual( + schema.fields.pointerField, + schema.fields.pointerJSONField + ); + assert.deepEqual( + schema.fields.pointerField.defaultValue, + pointer.toPointer() + ); assert.equal(schema.fields.pointerField.required, true); }); - it('set multiple required and default values', async () => { + 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 file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); + 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'); + const testSchema = new Parse.Schema("SchemaFieldTest"); testSchema - .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' }) - .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' } }) + .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", + }) + .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" }, + }); 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' }, - 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' } }, - fileField: { type: 'File', required: true, defaultValue: file.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' } + objectId: { type: "String" }, + updatedAt: { type: "Date" }, + createdAt: { type: "Date" }, + 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" }, + }, + fileField: { type: "File", required: true, defaultValue: file.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" }, }); - const object = new Parse.Object('SchemaFieldTest'); + const object = new Parse.Object("SchemaFieldTest"); await object.save(); const json = object.toJSON(); delete json.createdAt; @@ -177,53 +246,59 @@ describe('Schema', () => { delete json.objectId; const expected = { - defaultFieldString: 'hello', - stringField: 'world', + defaultFieldString: "hello", + stringField: "world", numberField: 10, booleanField: false, - dateField: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, - dateStringField: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, + dateField: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, + dateStringField: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, fileField: file.toJSON(), geoPointField: point.toJSON(), polygonField: { - __type: 'Polygon', - coordinates: [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] + __type: "Polygon", + coordinates: [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ], }, - arrayField: [ 1, 2, 3 ], - objectField: { foo: 'bar' }, + arrayField: [1, 2, 3], + objectField: { foo: "bar" }, }; assert.deepEqual(json, expected); }); - it('save class level permissions', async () => { + it("save class level permissions", async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { '*': true }, + create: { "*": true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; - const testSchema = new Parse.Schema('SchemaTest'); + const testSchema = new Parse.Schema("SchemaTest"); testSchema.setCLP(clp); const schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, clp); }); - it('update class level permissions', async () => { + it("update class level permissions", async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { '*': true }, + create: { "*": true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; - const testSchema = new Parse.Schema('SchemaTest'); + const testSchema = new Parse.Schema("SchemaTest"); let schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, defaultCLPS); @@ -240,18 +315,18 @@ describe('Schema', () => { assert.deepEqual(schema.classLevelPermissions, emptyCLPS); }); - it('update class level permissions multiple', async () => { + it("update class level permissions multiple", async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { '*': true }, + create: { "*": true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; - const testSchema = new Parse.Schema('SchemaTest'); + const testSchema = new Parse.Schema("SchemaTest"); testSchema.setCLP(clp); let schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, clp); @@ -263,131 +338,164 @@ describe('Schema', () => { assert.deepEqual(schema.classLevelPermissions, clp); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - 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(); + 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(); + }); + }) + .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) => { - const testSchema = new Parse.Schema('SchemaTest'); + 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.addString("name"); + testSchema.addIndex("test_index", index); testSchema.save().then((result) => { assert.notEqual(result.indexes.test_index, undefined); 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(); - }); + 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(); + }); }); - 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(); - }); + 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(); + }); }); - it('invalid field name', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid field name", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { testSchema.addField(null); } catch (e) { @@ -395,17 +503,17 @@ describe('Schema', () => { } }); - it('invalid field type', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid field type", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { - testSchema.addField('name', 'UnknownType'); + testSchema.addField("name", "UnknownType"); } catch (e) { done(); } }); - it('invalid index name', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid index name", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { testSchema.addIndex(null); } catch (e) { @@ -413,17 +521,17 @@ describe('Schema', () => { } }); - it('invalid index', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid index", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { - testSchema.addIndex('name', null); + testSchema.addIndex("name", null); } catch (e) { done(); } }); - it('invalid pointer name', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid pointer name", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { testSchema.addPointer(null); } catch (e) { @@ -431,17 +539,17 @@ describe('Schema', () => { } }); - it('invalid pointer class', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid pointer class", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { - testSchema.addPointer('name', null); + testSchema.addPointer("name", null); } catch (e) { done(); } }); - it('invalid relation name', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid relation name", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { testSchema.addRelation(null); } catch (e) { @@ -449,16 +557,16 @@ describe('Schema', () => { } }); - it('invalid relation class', (done) => { - const testSchema = new Parse.Schema('SchemaTest'); + it("invalid relation class", (done) => { + const testSchema = new Parse.Schema("SchemaTest"); try { - testSchema.addRelation('name', null); + testSchema.addRelation("name", null); } catch (e) { done(); } }); - 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..130956f2c 100644 --- a/integration/test/ParseSubclassTest.js +++ b/integration/test/ParseSubclassTest.js @@ -1,183 +1,203 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -describe('Parse Object Subclasses', () => { +describe("Parse Object Subclasses", () => { beforeEach((done) => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + 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) => { - const Subclass = Parse.Object.extend('Subclass', { + 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) => { - const Subclass = Parse.Object.extend('Subclass', { + 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) => { - const Container = Parse.Object.extend('Container'); - const Item = Parse.Object.extend('Item'); - const ItemChild = Parse.Object.extend('Item'); + 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) => { - const Parent = Parse.Object.extend('MyClass', { + 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) => { - const Parent = Parse.Object.extend('MyClass', { + 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', { + const Child = Parse.Object.extend("MyClass", { initialize() { Child.__super__.initialize.apply(this, arguments); this.child = true; - } + }, }); - const Grandchild = Parse.Object.extend('MyClass', { + 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) => { - const Parent = Parse.Object.extend('MyClass'); + 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 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 + it("propagates instance properties", () => { + const Squirtle = Parse.Object.extend("Squirtle", { + water: true, }); - const Wartortle = Squirtle.extend('Wartortle'); + const Wartortle = Squirtle.extend("Wartortle"); const wartortle = new Wartortle(); assert(wartortle.water); }); diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index e9d338bb9..99c71c3c1 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -1,10 +1,10 @@ -'use strict'; +"use strict"; -const assert = require('assert'); -const clear = require('./clear'); -const Parse = require('../../node'); +const assert = require("assert"); +const clear = require("./clear"); +const Parse = require("../../node"); -const TestObject = Parse.Object.extend('TestObject'); +const TestObject = Parse.Object.extend("TestObject"); class CustomUser extends Parse.User { constructor(attributes) { @@ -15,16 +15,16 @@ class CustomUser extends Parse.User { return 5; } } -Parse.Object.registerSubclass('CustomUser', CustomUser); +Parse.Object.registerSubclass("CustomUser", CustomUser); const provider = { authenticate: () => Promise.resolve(), restoreAuthentication: () => true, - getAuthType: () => 'anonymous', + getAuthType: () => "anonymous", getAuthData() { return { authData: { - id: '1234', + id: "1234", }, }; }, @@ -32,9 +32,9 @@ const provider = { Parse.User._registerAuthenticationProvider(provider); const authResponse = { - userID: 'test', - accessToken: 'test', - expiresIn: 'test', // Should be unix timestamp + userID: "test", + accessToken: "test", + expiresIn: "test", // Should be unix timestamp }; global.FB = { init: () => {}, @@ -44,38 +44,42 @@ global.FB = { getAuthResponse: () => authResponse, }; -describe('Parse User', () => { +describe("Parse User", () => { beforeAll(() => { - Parse.initialize('integration', null, 'notsosecret'); - Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.initialize("integration", null, "notsosecret"); + Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); Parse.Storage._clear(); - Parse.Object.registerSubclass('_User', Parse.User); + Parse.Object.registerSubclass("_User", Parse.User); }); 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.setPassword("asdf"); + user.setUsername("zxcv"); user.signUp().then((user) => { assert(user.getSessionToken()); expect(user.existed()).toBe(false); @@ -83,467 +87,531 @@ describe('Parse User', () => { }); }); - 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 () => { + it("can login users with installationId", async () => { Parse.User.enableUnsafeCurrentUser(); const currentInstallation = await Parse.CoreManager.getInstallationController().currentInstallationId(); - const installationId = '12345678'; + const installationId = "12345678"; const user = new Parse.User(); - user.set('username', 'parse'); - user.set('password', 'mypass'); + user.set("username", "parse"); + user.set("password", "mypass"); await user.signUp(null, { installationId }); const query = new Parse.Query(Parse.Session); - query.equalTo('user', user); + query.equalTo("user", user); const result = await query.first({ useMasterKey: true }); - expect(result.get('installationId')).toBe(installationId); - expect(result.get('sessionToken')).toBe(user.getSessionToken()); + expect(result.get("installationId")).toBe(installationId); + expect(result.get("sessionToken")).toBe(user.getSessionToken()); // Should not clean up sessions - const loggedUser = await Parse.User.logIn('parse', 'mypass'); + const loggedUser = await Parse.User.logIn("parse", "mypass"); const sessionQuery = new Parse.Query(Parse.Session); let sessions = await sessionQuery.find({ useMasterKey: true }); expect(sessions.length).toBe(2); - expect(sessions[0].get('installationId')).toBe(installationId); - expect(sessions[1].get('installationId')).toBe(currentInstallation); - expect(sessions[0].get('sessionToken')).toBe(user.getSessionToken()); - expect(sessions[1].get('sessionToken')).toBe(loggedUser.getSessionToken()); + expect(sessions[0].get("installationId")).toBe(installationId); + expect(sessions[1].get("installationId")).toBe(currentInstallation); + expect(sessions[0].get("sessionToken")).toBe(user.getSessionToken()); + 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); - expect(sessions[1].get('installationId')).toBe(installationId); - expect(sessions[0].get('sessionToken')).toBe(loggedUser.getSessionToken()); - expect(sessions[1].get('sessionToken')).toBe(installationUser.getSessionToken()); + expect(sessions[0].get("installationId")).toBe(currentInstallation); + expect(sessions[1].get("installationId")).toBe(installationId); + expect(sessions[0].get("sessionToken")).toBe(loggedUser.getSessionToken()); + 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({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', + password: "asdf", + 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 () => { + it("can fetch non-auth user with include", async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object('TestObject'); - child.set('field', 'test'); + const child = new Parse.Object("TestObject"); + child.set("field", "test"); const user = new Parse.User(); - user.set('password', 'asdf'); - user.set('email', 'asdf@exxample.com'); - user.set('username', 'zxcv'); - user.set('child', child); + user.set("password", "asdf"); + user.set("email", "asdf@exxample.com"); + user.set("username", "zxcv"); + user.set("child", child); await user.signUp(); const query = new Parse.Query(Parse.User); const userNotAuthed = await query.get(user.id); - assert.equal(userNotAuthed.get('child').get('field'), undefined); + assert.equal(userNotAuthed.get("child").get("field"), undefined); - const fetchedUser = await userNotAuthed.fetchWithInclude('child'); + const fetchedUser = await userNotAuthed.fetchWithInclude("child"); - assert.equal(userNotAuthed.get('child').get('field'), 'test'); - assert.equal(fetchedUser.get('child').get('field'), 'test'); + assert.equal(userNotAuthed.get("child").get("field"), "test"); + assert.equal(fetchedUser.get("child").get("field"), "test"); }); - it('can fetch auth user with include', async () => { + it("can fetch auth user with include", async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object('TestObject'); - child.set('field', 'test'); + const child = new Parse.Object("TestObject"); + child.set("field", "test"); let user = new Parse.User(); - user.set('password', 'asdf'); - user.set('email', 'asdf@exxample.com'); - user.set('username', 'zxcv'); - user.set('child', child); + user.set("password", "asdf"); + user.set("email", "asdf@exxample.com"); + user.set("username", "zxcv"); + user.set("child", child); await user.signUp(); - user = await Parse.User.logIn('zxcv', 'asdf'); + user = await Parse.User.logIn("zxcv", "asdf"); - assert.equal(user.get('child').get('field'), undefined); - assert.equal(Parse.User.current().get('child').get('field'), undefined); + assert.equal(user.get("child").get("field"), undefined); + assert.equal(Parse.User.current().get("child").get("field"), undefined); - const fetchedUser = await user.fetchWithInclude('child'); + const fetchedUser = await user.fetchWithInclude("child"); const current = await Parse.User.currentAsync(); - assert.equal(user.get('child').get('field'), 'test'); - assert.equal(current.get('child').get('field'), 'test'); - assert.equal(fetchedUser.get('child').get('field'), 'test'); - assert.equal(Parse.User.current().get('child').get('field'), 'test'); + assert.equal(user.get("child").get("field"), "test"); + assert.equal(current.get("child").get("field"), "test"); + assert.equal(fetchedUser.get("child").get("field"), "test"); + 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.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(); + }); }); - 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(); const user3 = new Parse.User(); - user1.set('username', 'a'); - user2.set('username', 'b'); - user3.set('username', 'c'); - - user1.set('password', 'password'); - 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.set("username", "a"); + user2.set("username", "b"); + user3.set("username", "c"); + + user1.set("password", "password"); + 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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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.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(); + }); }); - 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) => { - const SuperUser = Parse.Object.extend('User'); + it("handles user subclassing", (done) => { + const SuperUser = Parse.Object.extend("User"); const user = new SuperUser(); - user.set('username', 'bob'); - user.set('password', 'welcome'); + user.set("username", "bob"); + user.set("password", "welcome"); assert(user instanceof Parse.User); user.signUp().then(() => { done(); }); }); - 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(); }); }); - it('can save anonymous user', async () => { + it("can save anonymous user", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello'); + user.set("field", "hello"); await user.save(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get('field')).toBe('hello'); + expect(result.get("field")).toBe("hello"); }); - it('can not recover anonymous user if logged out', async () => { + it("can not recover anonymous user if logged out", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello'); + user.set("field", "hello"); await user.save(); await Parse.User.logOut(); @@ -552,75 +620,75 @@ describe('Parse User', () => { try { await query.get(user.id); } catch (error) { - expect(error.message).toBe('Object not found.'); + expect(error.message).toBe("Object not found."); } }); - it('can signUp anonymous user and retain data', async () => { + it("can signUp anonymous user and retain data", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello world'); + user.set("field", "hello world"); await user.save(); - expect(user.get('authData').anonymous).toBeDefined(); + expect(user.get("authData").anonymous).toBeDefined(); - user.setUsername('foo'); - user.setPassword('baz'); + user.setUsername("foo"); + user.setPassword("baz"); await user.signUp(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get('username')).toBe('foo'); - expect(result.get('authData')).toBeUndefined(); - expect(result.get('field')).toBe('hello world'); - expect(user.get('authData').anonymous).toBeUndefined(); + expect(result.get("username")).toBe("foo"); + expect(result.get("authData")).toBeUndefined(); + expect(result.get("field")).toBe("hello world"); + expect(user.get("authData").anonymous).toBeUndefined(); }); - it('can logIn user without converting anonymous user', async () => { + it("can logIn user without converting anonymous user", async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp('foobaz', '1234'); + await Parse.User.signUp("foobaz", "1234"); const user = await Parse.AnonymousUtils.logIn(); - user.set('field', 'hello world'); + user.set("field", "hello world"); await user.save(); - await Parse.User.logIn('foobaz', '1234'); + await Parse.User.logIn("foobaz", "1234"); const query = new Parse.Query(Parse.User); try { await query.get(user.id); } catch (error) { - expect(error.message).toBe('Object not found.'); + expect(error.message).toBe("Object not found."); } }); - it('anonymous user logIn does not use currentUser sessionToken', async () => { + it("anonymous user logIn does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = await Parse.AnonymousUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('anonymous user link currentUser', async () => { + it("anonymous user link currentUser", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = await Parse.AnonymousUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it('anonymous user link does not use currentUser sessionToken', async () => { + it("anonymous user link does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp('anon-not', '1234'); + const user1 = await Parse.User.signUp("anon-not", "1234"); const user2 = new Parse.User(); await Parse.AnonymousUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -628,33 +696,33 @@ describe('Parse User', () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('facebook logIn does not use currentUser sessionToken', async () => { + it("facebook logIn does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = await Parse.FacebookUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('facebook link currentUser', async () => { + it("facebook link currentUser", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = await Parse.FacebookUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it('facebook link does not use currentUser sessionToken', async () => { + it("facebook link does not use currentUser sessionToken", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp('facebook-not', '1234'); + const user1 = await Parse.User.signUp("facebook-not", "1234"); const user2 = new Parse.User(); await Parse.FacebookUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -662,27 +730,27 @@ describe('Parse User', () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it('can signUp user with subclass', async () => { + it("can signUp user with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); const user = await customUser.signUp(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can get current with subclass', async () => { + it("can get current with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - Parse.Object.registerSubclass('_User', CustomUser); + Parse.Object.registerSubclass("_User", CustomUser); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); await customUser.signUp(); Parse.User._clearCache(); @@ -690,91 +758,94 @@ describe('Parse User', () => { const user = CustomUser.current(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can logIn user with subclass', async () => { + it("can logIn user with subclass", async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp('username', 'password'); + await Parse.User.signUp("username", "password"); - const customUser = new CustomUser({ foo: 'bar' }); - customUser.setUsername('username'); - customUser.setPassword('password'); + const customUser = new CustomUser({ foo: "bar" }); + customUser.setUsername("username"); + customUser.setPassword("password"); const user = await customUser.logIn(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get('foo')).toBe('bar'); + expect(user.get("foo")).toBe("bar"); }); - it('can signUp / logIn user with subclass static', async () => { + it("can signUp / logIn user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + let user = await CustomUser.signUp("username", "password"); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - user = await CustomUser.logIn('username', 'password'); + user = await CustomUser.logIn("username", "password"); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can become user with subclass static', async () => { + it("can become user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + 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); }); - it('can get user (me) with subclass static', async () => { + it("can get user (me) with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp('username', 'password'); + 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); }); - it('can get hydrate user with subclass static', async () => { + it("can get hydrate user with subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); const user = await CustomUser.hydrate({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc', + objectId: "uid3", + username: "username", + sessionToken: "123abc", }); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can loginWith subclass static', async () => { + it("can loginWith subclass static", async () => { Parse.User.enableUnsafeCurrentUser(); let user = new CustomUser(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - user = await CustomUser.logInWith(provider.getAuthType(), provider.getAuthData()); + user = await CustomUser.logInWith( + provider.getAuthType(), + provider.getAuthData() + ); expect(user._isLinked(provider)).toBe(true); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it('can link without master key', async () => { + it("can link without master key", async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -782,58 +853,67 @@ describe('Parse User', () => { expect(user._isLinked(provider)).toBe(false); }); - it('can link with master key', async () => { + it("can link with master key", async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + 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); }); - it('can link with session token', async () => { + it("can link with session token", async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); 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); }); - it('linked account can login with authData', async () => { + it("linked account can login with authData", async () => { const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + 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(); - const loggedIn = await Parse.User.logInWith(provider.getAuthType(), provider.getAuthData()); + const loggedIn = await Parse.User.logInWith( + provider.getAuthType(), + provider.getAuthData() + ); expect(loggedIn.authenticated()).toBeTruthy(); }); - it('can linking un-authenticated user without master key', async () => { + it("can linking un-authenticated user without master key", async () => { const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.save(null, { useMasterKey: true }); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user.getSessionToken()).toBeDefined(); }); - it('can link with custom auth', async () => { + it("can link with custom auth", async () => { Parse.User.enableUnsafeCurrentUser(); const provider = { authenticate: () => Promise.resolve(), @@ -842,7 +922,7 @@ describe('Parse User', () => { }, getAuthType() { - return 'myAuth'; + return "myAuth"; }, getAuthData() { @@ -855,8 +935,8 @@ describe('Parse User', () => { }; Parse.User._registerAuthenticationProvider(provider); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -864,19 +944,19 @@ describe('Parse User', () => { expect(user._isLinked(provider)).toBe(false); }); - it('can login with facebook', async () => { + it("can login with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.FacebookUtils.logIn(); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); }); - it('can link user with facebook', async () => { + it("can link user with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); @@ -884,7 +964,7 @@ describe('Parse User', () => { expect(Parse.FacebookUtils.isLinked(user)).toBe(false); }); - it('can link anonymous user with facebook', async () => { + it("can link anonymous user with facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.AnonymousUtils.logIn(); @@ -898,30 +978,30 @@ describe('Parse User', () => { expect(Parse.AnonymousUtils.isLinked(user)).toBe(true); }); - it('can link with twitter', async () => { + it("can link with twitter", async () => { Parse.User.enableUnsafeCurrentUser(); const authData = { id: 227463280, consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr", }; const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - await user.linkWith('twitter', { authData }); + await user.linkWith("twitter", { authData }); - expect(user.get('authData').twitter.id).toBe(authData.id); - expect(user._isLinked('twitter')).toBe(true); + expect(user.get("authData").twitter.id).toBe(authData.id); + expect(user._isLinked("twitter")).toBe(true); - await user._unlinkFrom('twitter'); - expect(user._isLinked('twitter')).toBe(false); + await user._unlinkFrom("twitter"); + expect(user._isLinked("twitter")).toBe(false); }); - it('can link with twitter and facebook', async () => { + it("can link with twitter and facebook", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const authData = { @@ -929,65 +1009,68 @@ describe('Parse User', () => { consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr", }; const user = new Parse.User(); - user.setUsername('Alice'); - user.setPassword('sekrit'); + user.setUsername("Alice"); + user.setPassword("sekrit"); await user.signUp(); - await user.linkWith('twitter', { authData }); + await user.linkWith("twitter", { authData }); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); - expect(user._isLinked('twitter')).toBe(true); + expect(user._isLinked("twitter")).toBe(true); - expect(user.get('authData').twitter.id).toBe(authData.id); - expect(user.get('authData').facebook.id).toBe('test'); + expect(user.get("authData").twitter.id).toBe(authData.id); + expect(user.get("authData").facebook.id).toBe("test"); }); - it('can verify user password via static method', async () => { - await Parse.User.signUp('asd123', 'xyz123'); - const res = await Parse.User.verifyPassword('asd123', 'xyz123'); - expect(typeof res).toBe('object'); - expect(res.username).toBe('asd123'); + it("can verify user password via static method", async () => { + await Parse.User.signUp("asd123", "xyz123"); + const res = await Parse.User.verifyPassword("asd123", "xyz123"); + expect(typeof res).toBe("object"); + expect(res.username).toBe("asd123"); try { - await Parse.User.verifyPassword('asd123', 'wrong password'); + await Parse.User.verifyPassword("asd123", "wrong password"); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe('Invalid username/password.'); + expect(error.message).toBe("Invalid username/password."); } }); - it('can verify user password via instance method', async () => { - const user = await Parse.User.signUp('asd123', 'xyz123'); - const res = await user.verifyPassword('xyz123'); - expect(typeof res).toBe('object'); - expect(res.username).toBe('asd123'); + it("can verify user password via instance method", async () => { + const user = await Parse.User.signUp("asd123", "xyz123"); + const res = await user.verifyPassword("xyz123"); + expect(typeof res).toBe("object"); + expect(res.username).toBe("asd123"); try { - await user.verifyPassword('wrong password'); + await user.verifyPassword("wrong password"); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe('Invalid username/password.'); + expect(error.message).toBe("Invalid username/password."); } }); - it('can encrypt user', async () => { + it("can encrypt user", async () => { Parse.User.enableUnsafeCurrentUser(); Parse.enableEncryptedUser(); - Parse.secret = 'My Secret Key'; + Parse.secret = "My Secret Key"; const user = new Parse.User(); - user.setUsername('usernameENC'); - user.setPassword('passwordENC'); + user.setUsername("usernameENC"); + user.setPassword("passwordENC"); await user.signUp(); - const path = Parse.Storage.generatePath('currentUser'); + const path = Parse.Storage.generatePath("currentUser"); const encryptedUser = Parse.Storage.getItem(path); const crypto = Parse.CoreManager.getCryptoController(); - const decryptedUser = crypto.decrypt(encryptedUser, Parse.CoreManager.get('ENCRYPTED_KEY')); + const decryptedUser = crypto.decrypt( + encryptedUser, + Parse.CoreManager.get("ENCRYPTED_KEY") + ); expect(JSON.parse(decryptedUser).objectId).toBe(user.id); const currentUser = Parse.User.current(); @@ -996,22 +1079,22 @@ describe('Parse User', () => { const currentUserAsync = await Parse.User.currentAsync(); expect(currentUserAsync).toEqual(user); await Parse.User.logOut(); - Parse.CoreManager.set('ENCRYPTED_USER', false); - Parse.CoreManager.set('ENCRYPTED_KEY', null); + Parse.CoreManager.set("ENCRYPTED_USER", false); + Parse.CoreManager.set("ENCRYPTED_KEY", null); }); - it('fix GHSA-wvh7-5p38-2qfc', async () => { + it("fix GHSA-wvh7-5p38-2qfc", async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername('username'); - user.setPassword('password'); + user.setUsername("username"); + user.setPassword("password"); await user.signUp(); - const path = Parse.Storage.generatePath('currentUser'); + const path = Parse.Storage.generatePath("currentUser"); let userData = Parse.Storage.getItem(path); expect(JSON.parse(userData).password).toBeUndefined(); - user.setPassword('password'); + user.setPassword("password"); await user.save(null, { useMasterKey: true }); userData = Parse.Storage.getItem(path); diff --git a/integration/test/clear.js b/integration/test/clear.js index ed8ae85c2..bbb1aa2e8 100644 --- a/integration/test/clear.js +++ b/integration/test/clear.js @@ -1,4 +1,4 @@ -const Parse = require('../../node'); +const Parse = require("../../node"); /** * Destroys all data in the database @@ -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) { - return Parse._ajax('GET', `http://localhost:1337/clear/${fast}`, ''); +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..1663c2948 100644 --- a/integration/test/helper.js +++ b/integration/test/helper.js @@ -1,12 +1,12 @@ -const ParseServer = require('parse-server').ParseServer; +const ParseServer = require("parse-server").ParseServer; jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; beforeAll((done) => { - const { app } = require('../server'); - const httpServer = require('http').createServer(app); + const { app } = require("../server"); + const httpServer = require("http").createServer(app); - httpServer.on('error', console.log).listen(1337, () => { - console.log('parse-server running on port 1337.'); + httpServer.on("error", console.log).listen(1337, () => { + console.log("parse-server running on port 1337."); done(); }); ParseServer.createLiveQueryServer(httpServer); diff --git a/integration/test/mockLocalStorage.js b/integration/test/mockLocalStorage.js index eadaf9731..ef7cadd13 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; }, 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..58b4286bc 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..508aca5bd 100644 --- a/src/Analytics.js +++ b/src/Analytics.js @@ -9,7 +9,7 @@ * @flow */ -import CoreManager from './CoreManager'; +import CoreManager from "./CoreManager"; /** * Parse.Analytics provides an interface to Parse's logging and analytics @@ -55,31 +55,30 @@ export function track( name: string, dimensions: { [key: string]: string } ): Promise { - name = name || ''; - name = name.replace(/^\s*/, ''); - name = name.replace(/\s*$/, ''); + name = name || ""; + name = name.replace(/^\s*/, ""); + name = name.replace(/\s*$/, ""); if (name.length === 0) { - throw new TypeError('A name for the custom event must be provided'); + throw new TypeError("A name for the custom event must be provided"); } for (const key in dimensions) { - if (typeof key !== 'string' || typeof dimensions[key] !== 'string') { + if (typeof key !== "string" || typeof dimensions[key] !== "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 = { track(name, dimensions) { - const path = 'events/' + name; + const path = "events/" + name; const RESTController = CoreManager.getRESTController(); - return RESTController.request('POST', path, { dimensions: dimensions }); - } + return RESTController.request("POST", path, { dimensions: dimensions }); + }, }; CoreManager.setAnalyticsController(DefaultController); diff --git a/src/AnonymousUtils.js b/src/AnonymousUtils.js index 630d18f0f..3f602aab5 100644 --- a/src/AnonymousUtils.js +++ b/src/AnonymousUtils.js @@ -9,9 +9,9 @@ * @flow-weak */ -import ParseUser from './ParseUser'; -import type { RequestOptions } from './RESTController'; -const uuidv4 = require('uuid/v4'); +import ParseUser from "./ParseUser"; +import type { RequestOptions } from "./RESTController"; +const uuidv4 = require("uuid/v4"); let registered = false; @@ -71,7 +71,11 @@ const AnonymousUtils = { */ logIn(options?: RequestOptions): Promise { const provider = this._getAuthProvider(); - return ParseUser.logInWith(provider.getAuthType(), provider.getAuthData(), options); + return ParseUser.logInWith( + provider.getAuthType(), + provider.getAuthData(), + options + ); }, /** @@ -86,7 +90,11 @@ const AnonymousUtils = { */ link(user: ParseUser, options?: RequestOptions): Promise { const provider = this._getAuthProvider(); - return user.linkWith(provider.getAuthType(), provider.getAuthData(), options); + return user.linkWith( + provider.getAuthType(), + provider.getAuthData(), + options + ); }, _getAuthProvider() { @@ -96,7 +104,7 @@ const AnonymousUtils = { }, getAuthType() { - return 'anonymous'; + return "anonymous"; }, getAuthData() { @@ -112,7 +120,7 @@ const AnonymousUtils = { registered = true; } return provider; - } + }, }; export default AnonymousUtils; diff --git a/src/Cloud.js b/src/Cloud.js index 5471ac740..1d015cada 100644 --- a/src/Cloud.js +++ b/src/Cloud.js @@ -9,13 +9,13 @@ * @flow */ -import CoreManager from './CoreManager'; -import decode from './decode'; -import encode from './encode'; -import ParseError from './ParseError'; -import ParseQuery from './ParseQuery'; -import ParseObject from './ParseObject'; -import type { RequestOptions } from './RESTController'; +import CoreManager from "./CoreManager"; +import decode from "./decode"; +import encode from "./encode"; +import ParseError from "./ParseError"; +import ParseQuery from "./ParseQuery"; +import ParseObject from "./ParseObject"; +import type { RequestOptions } from "./RESTController"; /** * Contains functions for calling and declaring @@ -47,8 +47,8 @@ export function run( ): Promise { options = options || {}; - if (typeof name !== 'string' || name.length === 0) { - throw new TypeError('Cloud function name must be a string.'); + if (typeof name !== "string" || name.length === 0) { + throw new TypeError("Cloud function name must be a string."); } const requestOptions = {}; @@ -58,7 +58,7 @@ export function run( if (options.sessionToken) { requestOptions.sessionToken = options.sessionToken; } - if (options.context && typeof options.context === 'object') { + if (options.context && typeof options.context === "object") { requestOptions.context = options.context; } @@ -75,7 +75,7 @@ export function run( */ export function getJobsData(): Promise { const requestOptions = { - useMasterKey: true + useMasterKey: true, }; return CoreManager.getCloudController().getJobsData(requestOptions); } @@ -90,16 +90,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 { - - if (typeof name !== 'string' || name.length === 0) { - throw new TypeError('Cloud job name must be a string.'); +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); } @@ -113,7 +109,7 @@ export function startJob( * @returns {Parse.Object} Status of Job. */ export function getJobStatus(jobStatusId: string): Promise { - const query = new ParseQuery('_JobStatus'); + const query = new ParseQuery("_JobStatus"); return query.get(jobStatusId, { useMasterKey: true }); } @@ -124,23 +120,25 @@ const DefaultController = { const payload = encode(data, true); const request = RESTController.request( - 'POST', - 'functions/' + name, + "POST", + "functions/" + name, payload, options ); return request.then((res) => { - if (typeof res === 'object' && - Object.keys(res).length > 0 && - !res.hasOwnProperty('result')) { + if ( + typeof res === "object" && + Object.keys(res).length > 0 && + !res.hasOwnProperty("result") + ) { throw new ParseError( ParseError.INVALID_JSON, - 'The server returned an invalid response.' + "The server returned an invalid response." ); } const decoded = decode(res); - if (decoded && decoded.hasOwnProperty('result')) { + if (decoded && decoded.hasOwnProperty("result")) { return Promise.resolve(decoded.result); } return Promise.resolve(undefined); @@ -150,12 +148,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 +156,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..417b8634e 100644 --- a/src/CoreManager.js +++ b/src/CoreManager.js @@ -9,147 +9,203 @@ * @flow */ -import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; -import type ParseFile from './ParseFile'; -import type { FileSource } from './ParseFile'; -import type { Op } from './ParseOp'; -import type ParseObject from './ParseObject'; -import type { QueryJSON } from './ParseQuery'; -import type ParseUser from './ParseUser'; -import type { AuthData } from './ParseUser'; -import type { PushData } from './Push'; -import type { RequestOptions, FullOptions } from './RESTController'; +import type { + AttributeMap, + ObjectCache, + OpsMap, + State, +} from "./ObjectStateMutations"; +import type ParseFile from "./ParseFile"; +import type { FileSource } from "./ParseFile"; +import type { Op } from "./ParseOp"; +import type ParseObject from "./ParseObject"; +import type { QueryJSON } from "./ParseQuery"; +import type ParseUser from "./ParseUser"; +import type { AuthData } from "./ParseUser"; +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,19 +228,20 @@ 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: {}, - SERVER_URL: 'https://api.parse.com/1', + SERVER_URL: "https://api.parse.com/1", SERVER_AUTH_TYPE: null, SERVER_AUTH_TOKEN: null, LIVEQUERY_SERVER_URL: null, ENCRYPTED_KEY: null, - VERSION: 'js' + require('../package.json').version, + VERSION: "js" + require("../package.json").version, APPLICATION_ID: null, JAVASCRIPT_KEY: null, MASTER_KEY: null, @@ -192,269 +249,304 @@ 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) => { - if (typeof controller[func] !== 'function') { + if (typeof controller[func] !== "function") { throw new Error(`${name} must implement ${func}()`); } }); } 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); + 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; }, /* Specialized Controller Setters/Getters */ setAnalyticsController(controller: AnalyticsController) { - requireMethods('AnalyticsController', ['track'], controller); - config['AnalyticsController'] = controller; + requireMethods("AnalyticsController", ["track"], controller); + config["AnalyticsController"] = controller; }, getAnalyticsController(): AnalyticsController { - return config['AnalyticsController']; + return config["AnalyticsController"]; }, setCloudController(controller: CloudController) { - requireMethods('CloudController', ['run', 'getJobsData', 'startJob'], controller); - config['CloudController'] = controller; + requireMethods( + "CloudController", + ["run", "getJobsData", "startJob"], + controller + ); + config["CloudController"] = controller; }, getCloudController(): CloudController { - return config['CloudController']; + return config["CloudController"]; }, setConfigController(controller: ConfigController) { - requireMethods('ConfigController', ['current', 'get', 'save'], controller); - config['ConfigController'] = controller; + requireMethods("ConfigController", ["current", "get", "save"], controller); + config["ConfigController"] = controller; }, getConfigController(): ConfigController { - return config['ConfigController']; + return config["ConfigController"]; }, setCryptoController(controller: CryptoController) { - requireMethods('CryptoController', ['encrypt', 'decrypt'], controller); - config['CryptoController'] = controller; + requireMethods("CryptoController", ["encrypt", "decrypt"], controller); + config["CryptoController"] = controller; }, getCryptoController(): CryptoController { - return config['CryptoController']; + return config["CryptoController"]; }, setFileController(controller: FileController) { - requireMethods('FileController', ['saveFile', 'saveBase64'], controller); - config['FileController'] = controller; + requireMethods("FileController", ["saveFile", "saveBase64"], controller); + config["FileController"] = controller; }, getFileController(): FileController { - return config['FileController']; + return config["FileController"]; }, setInstallationController(controller: InstallationController) { - requireMethods('InstallationController', ['currentInstallationId'], controller); - config['InstallationController'] = controller; + requireMethods( + "InstallationController", + ["currentInstallationId"], + controller + ); + config["InstallationController"] = controller; }, getInstallationController(): InstallationController { - return config['InstallationController']; + return config["InstallationController"]; }, setObjectController(controller: ObjectController) { - requireMethods('ObjectController', ['save', 'fetch', 'destroy'], controller); - config['ObjectController'] = controller; + requireMethods( + "ObjectController", + ["save", "fetch", "destroy"], + controller + ); + config["ObjectController"] = controller; }, getObjectController(): ObjectController { - return config['ObjectController']; + return config["ObjectController"]; }, setObjectStateController(controller: ObjectStateController) { - requireMethods('ObjectStateController', [ - 'getState', - 'initializeState', - 'removeState', - 'getServerData', - 'setServerData', - 'getPendingOps', - 'setPendingOp', - 'pushPendingState', - 'popPendingState', - 'mergeFirstPendingState', - 'getObjectCache', - 'estimateAttribute', - 'estimateAttributes', - 'commitServerChanges', - 'enqueueTask', - 'clearAllState', - ], controller); - - config['ObjectStateController'] = controller; + requireMethods( + "ObjectStateController", + [ + "getState", + "initializeState", + "removeState", + "getServerData", + "setServerData", + "getPendingOps", + "setPendingOp", + "pushPendingState", + "popPendingState", + "mergeFirstPendingState", + "getObjectCache", + "estimateAttribute", + "estimateAttributes", + "commitServerChanges", + "enqueueTask", + "clearAllState", + ], + controller + ); + + config["ObjectStateController"] = controller; }, getObjectStateController(): ObjectStateController { - return config['ObjectStateController']; + return config["ObjectStateController"]; }, setPushController(controller: PushController) { - requireMethods('PushController', ['send'], controller); - config['PushController'] = controller; + requireMethods("PushController", ["send"], controller); + config["PushController"] = controller; }, getPushController(): PushController { - return config['PushController']; + return config["PushController"]; }, setQueryController(controller: QueryController) { - requireMethods('QueryController', ['find', 'aggregate'], controller); - config['QueryController'] = controller; + requireMethods("QueryController", ["find", "aggregate"], controller); + config["QueryController"] = controller; }, getQueryController(): QueryController { - return config['QueryController']; + return config["QueryController"]; }, setRESTController(controller: RESTController) { - requireMethods('RESTController', ['request', 'ajax'], controller); - config['RESTController'] = controller; + requireMethods("RESTController", ["request", "ajax"], controller); + config["RESTController"] = controller; }, getRESTController(): RESTController { - return config['RESTController']; + return config["RESTController"]; }, setSchemaController(controller: SchemaController) { - requireMethods('SchemaController', ['get', 'create', 'update', 'delete', 'send', 'purge'], controller); - config['SchemaController'] = controller; + requireMethods( + "SchemaController", + ["get", "create", "update", "delete", "send", "purge"], + controller + ); + config["SchemaController"] = controller; }, getSchemaController(): SchemaController { - return config['SchemaController']; + return config["SchemaController"]; }, setSessionController(controller: SessionController) { - requireMethods('SessionController', ['getSession'], controller); - config['SessionController'] = controller; + requireMethods("SessionController", ["getSession"], controller); + config["SessionController"] = controller; }, getSessionController(): SessionController { - return config['SessionController']; + return config["SessionController"]; }, 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; + config["StorageController"] = controller; }, setLocalDatastoreController(controller: LocalDatastoreController) { - requireMethods('LocalDatastoreController', ['pinWithName', 'fromPinWithName', 'unPinWithName', 'getAllContents', 'clear'], controller); - config['LocalDatastoreController'] = controller; + requireMethods( + "LocalDatastoreController", + [ + "pinWithName", + "fromPinWithName", + "unPinWithName", + "getAllContents", + "clear", + ], + controller + ); + config["LocalDatastoreController"] = controller; }, getLocalDatastoreController(): LocalDatastoreController { - return config['LocalDatastoreController']; + return config["LocalDatastoreController"]; }, setLocalDatastore(store: any) { - config['LocalDatastore'] = store; + config["LocalDatastore"] = store; }, getLocalDatastore() { - return config['LocalDatastore']; + return config["LocalDatastore"]; }, getStorageController(): StorageController { - return config['StorageController']; + return config["StorageController"]; }, setAsyncStorage(storage: any) { - config['AsyncStorage'] = storage; + config["AsyncStorage"] = storage; }, getAsyncStorage() { - return config['AsyncStorage']; + return config["AsyncStorage"]; }, setWebSocketController(controller: WebSocketController) { - config['WebSocketController'] = controller; + config["WebSocketController"] = controller; }, getWebSocketController(): WebSocketController { - return config['WebSocketController']; + return config["WebSocketController"]; }, setUserController(controller: UserController) { - requireMethods('UserController', [ - 'setCurrentUser', - 'currentUser', - 'currentUserAsync', - 'signUp', - 'logIn', - 'become', - 'logOut', - 'me', - 'requestPasswordReset', - 'upgradeToRevocableSession', - 'requestEmailVerification', - 'verifyPassword', - 'linkWith', - ], controller); - config['UserController'] = controller; + requireMethods( + "UserController", + [ + "setCurrentUser", + "currentUser", + "currentUserAsync", + "signUp", + "logIn", + "become", + "logOut", + "me", + "requestPasswordReset", + "upgradeToRevocableSession", + "requestEmailVerification", + "verifyPassword", + "linkWith", + ], + controller + ); + config["UserController"] = controller; }, getUserController(): UserController { - return config['UserController']; + return config["UserController"]; }, setLiveQueryController(controller: any) { - requireMethods('LiveQueryController', [ - 'setDefaultLiveQueryClient', - 'getDefaultLiveQueryClient', - '_clearCachedDefaultClient', - ], controller); - config['LiveQueryController'] = controller; + requireMethods( + "LiveQueryController", + [ + "setDefaultLiveQueryClient", + "getDefaultLiveQueryClient", + "_clearCachedDefaultClient", + ], + controller + ); + config["LiveQueryController"] = controller; }, getLiveQueryController(): any { - return config['LiveQueryController']; + return config["LiveQueryController"]; }, setHooksController(controller: HooksController) { - requireMethods('HooksController', [ - 'create', - 'get', - 'update', - 'remove', - ], controller); - config['HooksController'] = controller; + requireMethods( + "HooksController", + ["create", "get", "update", "remove"], + controller + ); + config["HooksController"] = controller; }, getHooksController(): HooksController { - return config['HooksController']; - } -} + return config["HooksController"]; + }, +}; diff --git a/src/CryptoController.js b/src/CryptoController.js index 49b7fc725..173c820b3 100644 --- a/src/CryptoController.js +++ b/src/CryptoController.js @@ -1,13 +1,13 @@ let AES; let ENC; -if (process.env.PARSE_BUILD === 'react-native') { - const CryptoJS = require('react-native-crypto-js'); +if (process.env.PARSE_BUILD === "react-native") { + const CryptoJS = require("react-native-crypto-js"); AES = CryptoJS.AES; ENC = CryptoJS.enc.Utf8; } else { - AES = require('crypto-js/aes'); - ENC = require('crypto-js/enc-utf8'); + AES = require("crypto-js/aes"); + ENC = require("crypto-js/enc-utf8"); } const CryptoController = { diff --git a/src/EventEmitter.js b/src/EventEmitter.js index 47d6a1c85..c9351f9be 100644 --- a/src/EventEmitter.js +++ b/src/EventEmitter.js @@ -9,10 +9,10 @@ * This is a simple wrapper to unify EventEmitter implementations across platforms. */ -if (process.env.PARSE_BUILD === 'react-native') { - const EventEmitter = require('../../../react-native/Libraries/vendor/emitter/EventEmitter'); +if (process.env.PARSE_BUILD === "react-native") { + const EventEmitter = require("../../../react-native/Libraries/vendor/emitter/EventEmitter"); EventEmitter.prototype.on = EventEmitter.prototype.addListener; module.exports = EventEmitter; } else { - module.exports = require('events').EventEmitter; + module.exports = require("events").EventEmitter; } diff --git a/src/FacebookUtils.js b/src/FacebookUtils.js index 6c6d2a764..06111f00b 100644 --- a/src/FacebookUtils.js +++ b/src/FacebookUtils.js @@ -9,34 +9,38 @@ * @flow-weak */ /* global FB */ -import ParseUser from './ParseUser'; +import ParseUser from "./ParseUser"; let initialized = false; let requestedPermissions; let initOptions; const provider = { authenticate(options) { - if (typeof FB === 'undefined') { - options.error(this, 'Facebook SDK not found.'); + 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(); } @@ -66,12 +69,12 @@ const provider = { }, getAuthType() { - return 'facebook'; + return "facebook"; }, deauthenticate() { this.restoreAuthentication(null); - } + }, }; /** @@ -101,9 +104,9 @@ const FacebookUtils = { * explicitly if this behavior is required by your application. */ init(options) { - if (typeof FB === 'undefined') { + if (typeof FB === "undefined") { throw new Error( - 'The Facebook JavaScript SDK must be loaded before calling init.' + "The Facebook JavaScript SDK must be loaded before calling init." ); } initOptions = {}; @@ -112,12 +115,15 @@ const FacebookUtils = { initOptions[key] = options[key]; } } - 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.'); + 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." + ); } initOptions.status = false; FB.init(initOptions); @@ -136,7 +142,7 @@ const FacebookUtils = { * linked to Facebook. */ isLinked(user) { - return user._isLinked('facebook'); + return user._isLinked("facebook"); }, /** @@ -164,17 +170,17 @@ const FacebookUtils = { * @returns {Promise} */ logIn(permissions, options) { - if (!permissions || typeof permissions === 'string') { + if (!permissions || typeof permissions === "string") { if (!initialized) { throw new Error( - 'You must initialize FacebookUtils before calling logIn.' + "You must initialize FacebookUtils before calling logIn." ); } requestedPermissions = permissions; - return ParseUser.logInWith('facebook', options); + return ParseUser.logInWith("facebook", options); } const authData = { authData: permissions }; - return ParseUser.logInWith('facebook', authData, options); + return ParseUser.logInWith("facebook", authData, options); }, /** @@ -204,17 +210,17 @@ const FacebookUtils = { * @returns {Promise} */ link(user, permissions, options) { - if (!permissions || typeof permissions === 'string') { + if (!permissions || typeof permissions === "string") { if (!initialized) { throw new Error( - 'You must initialize FacebookUtils before calling link.' + "You must initialize FacebookUtils before calling link." ); } requestedPermissions = permissions; - return user.linkWith('facebook', options); + return user.linkWith("facebook", options); } const authData = { authData: permissions }; - return user.linkWith('facebook', authData, options); + return user.linkWith("facebook", authData, options); }, /** @@ -228,19 +234,19 @@ 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.' + "You must initialize FacebookUtils before calling unlink." ); } - return user._unlinkFrom('facebook', options); + return user._unlinkFrom("facebook", options); }, // Used for testing purposes _getAuthProvider() { return provider; - } + }, }; export default FacebookUtils; diff --git a/src/InstallationController.js b/src/InstallationController.js index 2611abe9f..9ad01aaf4 100644 --- a/src/InstallationController.js +++ b/src/InstallationController.js @@ -9,17 +9,17 @@ * @flow */ -import Storage from './Storage'; -const uuidv4 = require('uuid/v4'); +import Storage from "./Storage"; +const uuidv4 = require("uuid/v4"); let iidCache = null; const InstallationController = { currentInstallationId(): Promise { - if (typeof iidCache === 'string') { + if (typeof iidCache === "string") { return Promise.resolve(iidCache); } - const path = Storage.generatePath('installationId'); + const path = Storage.generatePath("installationId"); return Storage.getItemAsync(path).then((iid) => { if (!iid) { iid = uuidv4(); @@ -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..88f1bf90d 100644 --- a/src/LiveQueryClient.js +++ b/src/LiveQueryClient.js @@ -9,66 +9,65 @@ */ /* global WebSocket */ -import CoreManager from './CoreManager'; -import EventEmitter from './EventEmitter'; -import ParseObject from './ParseObject'; -import LiveQuerySubscription from './LiveQuerySubscription'; -import { resolvingPromise } from './promiseUtils'; +import CoreManager from "./CoreManager"; +import EventEmitter from "./EventEmitter"; +import ParseObject from "./ParseObject"; +import LiveQuerySubscription from "./LiveQuerySubscription"; +import { resolvingPromise } from "./promiseUtils"; // The LiveQuery client inner state const CLIENT_STATE = { - INITIALIZED: 'initialized', - CONNECTING: 'connecting', - CONNECTED: 'connected', - CLOSED: 'closed', - RECONNECTING: 'reconnecting', - DISCONNECTED: 'disconnected' + INITIALIZED: "initialized", + CONNECTING: "connecting", + CONNECTED: "connected", + CLOSED: "closed", + RECONNECTING: "reconnecting", + DISCONNECTED: "disconnected", }; // The event type the LiveQuery client should sent to server const OP_TYPES = { - CONNECT: 'connect', - SUBSCRIBE: 'subscribe', - UNSUBSCRIBE: 'unsubscribe', - ERROR: 'error' + CONNECT: "connect", + SUBSCRIBE: "subscribe", + UNSUBSCRIBE: "unsubscribe", + ERROR: "error", }; // The event we get back from LiveQuery server const OP_EVENTS = { - CONNECTED: 'connected', - SUBSCRIBED: 'subscribed', - UNSUBSCRIBED: 'unsubscribed', - ERROR: 'error', - CREATE: 'create', - UPDATE: 'update', - ENTER: 'enter', - LEAVE: 'leave', - DELETE: 'delete' + CONNECTED: "connected", + SUBSCRIBED: "subscribed", + UNSUBSCRIBED: "unsubscribed", + ERROR: "error", + CREATE: "create", + UPDATE: "update", + ENTER: "enter", + LEAVE: "leave", + DELETE: "delete", }; // The event the LiveQuery client should emit const CLIENT_EMMITER_TYPES = { - CLOSE: 'close', - ERROR: 'error', - OPEN: 'open' + CLOSE: "close", + ERROR: "error", + OPEN: "open", }; // The event the LiveQuery subscription should emit const SUBSCRIPTION_EMMITER_TYPES = { - OPEN: 'open', - CLOSE: 'close', - ERROR: 'error', - CREATE: 'create', - UPDATE: 'update', - ENTER: 'enter', - LEAVE: 'leave', - DELETE: 'delete' + OPEN: "open", + CLOSE: "close", + ERROR: "error", + CREATE: "create", + UPDATE: "update", + ENTER: "enter", + LEAVE: "leave", + DELETE: "delete", }; - const generateInterval = (k) => { - return Math.random() * Math.min(30, (Math.pow(2, k) - 1)) * 1000; -} + return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000; +}; /** * Creates a new LiveQueryClient. @@ -149,8 +148,10 @@ 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'); + if (!serverURL || serverURL.indexOf("ws") !== 0) { + throw new Error( + "You need to set a proper Parse LiveQuery server url before using LiveQueryClient" + ); } this.reconnectHandle = null; @@ -170,11 +171,14 @@ class LiveQueryClient extends EventEmitter { // adding listener so process does not crash // best practice is for developer to register their own listener - this.on('error', () => {}); + this.on("error", () => {}); } shouldOpen(): any { - return this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED; + return ( + this.state === CLIENT_STATE.INITIALIZED || + this.state === CLIENT_STATE.DISCONNECTED + ); } /** @@ -198,22 +202,26 @@ class LiveQueryClient extends EventEmitter { const className = query.className; const queryJSON = query.toJSON(); const where = queryJSON.where; - const fields = queryJSON.keys ? queryJSON.keys.split(',') : undefined; + const fields = queryJSON.keys ? queryJSON.keys.split(",") : undefined; const subscribeRequest = { op: OP_TYPES.SUBSCRIBE, requestId: this.requestId, query: { className, where, - fields - } + fields, + }, }; if (sessionToken) { subscribeRequest.sessionToken = sessionToken; } - const subscription = new LiveQuerySubscription(this.requestId, query, sessionToken); + const subscription = new LiveQuerySubscription( + this.requestId, + query, + sessionToken + ); this.subscriptions.set(this.requestId, subscription); this.requestId += 1; this.connectPromise.then(() => { @@ -236,8 +244,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)); }); @@ -251,7 +259,10 @@ class LiveQueryClient extends EventEmitter { open() { const WebSocketImplementation = CoreManager.getWebSocketController(); if (!WebSocketImplementation) { - this.emit(CLIENT_EMMITER_TYPES.ERROR, 'Can not find WebSocket implementation'); + this.emit( + CLIENT_EMMITER_TYPES.ERROR, + "Can not find WebSocket implementation" + ); return; } @@ -284,7 +295,7 @@ class LiveQueryClient extends EventEmitter { const query = subscription.query; const queryJSON = query.toJSON(); const where = queryJSON.where; - const fields = queryJSON.keys ? queryJSON.keys.split(',') : undefined; + const fields = queryJSON.keys ? queryJSON.keys.split(",") : undefined; const className = query.className; const sessionToken = subscription.sessionToken; const subscribeRequest = { @@ -293,8 +304,8 @@ class LiveQueryClient extends EventEmitter { query: { className, where, - fields - } + fields, + }, }; if (sessionToken) { @@ -313,7 +324,10 @@ class LiveQueryClient extends EventEmitter { * */ close() { - if (this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED) { + if ( + this.state === CLIENT_STATE.INITIALIZED || + this.state === CLIENT_STATE.DISCONNECTED + ) { return; } this.state = CLIENT_STATE.DISCONNECTED; @@ -343,7 +357,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; @@ -353,19 +367,18 @@ class LiveQueryClient extends EventEmitter { _handleWebSocketMessage(event: any) { let data = event.data; - if (typeof data === 'string') { + if (typeof data === "string") { data = JSON.parse(data); } 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(); @@ -379,19 +392,26 @@ class LiveQueryClient extends EventEmitter { if (subscription) { subscription.subscribed = true; subscription.subscribePromise.resolve(); - setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), 200); + setTimeout( + () => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), + 200 + ); } break; case OP_EVENTS.ERROR: if (data.requestId) { if (subscription) { subscription.subscribePromise.resolve(); - setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), 200); + setTimeout( + () => + subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), + 200 + ); } } else { this.emit(CLIENT_EMMITER_TYPES.ERROR, data.error); } - if (data.error === 'Additional properties not allowed') { + if (data.error === "Additional properties not allowed") { this.additionalProperties = false; } if (data.reconnect) { @@ -474,21 +494,28 @@ 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); -} else if (process.env.PARSE_BUILD === 'weapp') { - CoreManager.setWebSocketController(require('./Socket.weapp')); -} else if (process.env.PARSE_BUILD === 'react-native') { +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 + ); +} else if (process.env.PARSE_BUILD === "weapp") { + CoreManager.setWebSocketController(require("./Socket.weapp")); +} else if (process.env.PARSE_BUILD === "react-native") { CoreManager.setWebSocketController(WebSocket); } diff --git a/src/LiveQuerySubscription.js b/src/LiveQuerySubscription.js index 197143a80..af53ae77a 100644 --- a/src/LiveQuerySubscription.js +++ b/src/LiveQuerySubscription.js @@ -8,9 +8,9 @@ * */ -import EventEmitter from './EventEmitter'; -import CoreManager from './CoreManager'; -import { resolvingPromise } from './promiseUtils'; +import EventEmitter from "./EventEmitter"; +import CoreManager from "./CoreManager"; +import { resolvingPromise } from "./promiseUtils"; /** * Creates a new LiveQuery Subscription. @@ -113,7 +113,7 @@ class Subscription extends EventEmitter { // adding listener so process does not crash // best practice is for developer to register their own listener - this.on('error', () => {}); + this.on("error", () => {}); } /** @@ -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..6497487ff 100644 --- a/src/LocalDatastore.js +++ b/src/LocalDatastore.js @@ -9,11 +9,11 @@ * @flow */ -import CoreManager from './CoreManager'; +import CoreManager from "./CoreManager"; -import type ParseObject from './ParseObject'; -import ParseQuery from './ParseQuery'; -import { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX } from './LocalDatastoreUtils'; +import type ParseObject from "./ParseObject"; +import ParseQuery from "./ParseQuery"; +import { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX } from "./LocalDatastoreUtils"; /** * Provides a local datastore which can be used to store and retrieve Parse.Object.
@@ -72,7 +72,10 @@ const LocalDatastore = { // Pin the object and children recursively // Saves the object and children key to Pin Name - async _handlePinAllWithName(name: string, objects: Array): Promise { + async _handlePinAllWithName( + name: string, + objects: Array + ): Promise { const pinName = this.getPinName(name); const toPinPromises = []; const objectKeys = []; @@ -110,7 +113,7 @@ const LocalDatastore = { objectKeys = [...new Set(objectKeys)]; let pinned = localDatastore[pinName] || []; - pinned = pinned.filter(item => !objectKeys.includes(item)); + pinned = pinned.filter((item) => !objectKeys.includes(item)); if (pinned.length == 0) { promises.push(this.unPinWithName(pinName)); delete localDatastore[pinName]; @@ -141,7 +144,7 @@ const LocalDatastore = { const encountered = {}; const json = object._toFullJSON(undefined, true); for (const key in json) { - if (json[key] && json[key].__type && json[key].__type === 'Object') { + if (json[key] && json[key].__type && json[key].__type === "Object") { this._traverse(json[key], encountered); } } @@ -163,7 +166,7 @@ const LocalDatastore = { if (!object[key]) { json = object; } - if (json.__type && json.__type === 'Object') { + if (json.__type && json.__type === "Object") { this._traverse(json, encountered); } } @@ -189,7 +192,7 @@ const LocalDatastore = { const promises = pinned.map((objectKey) => this.fromPinWithName(objectKey)); let objects = await Promise.all(promises); objects = [].concat(...objects); - return objects.filter(object => object != null); + return objects.filter((object) => object != null); }, // Replaces object pointers with pinned pointers @@ -211,12 +214,12 @@ 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) { const value = subTreeRoot[field]; - if (value.__type && value.__type === 'Object') { + if (value.__type && value.__type === "Object") { const key = this.getKeyForObject(value); if (LDS[key] && LDS[key].length > 0) { const pointer = LDS[key][0]; @@ -258,16 +261,14 @@ const LocalDatastore = { if (!pin) { return; } - const promises = [ - this.unPinWithName(objectKey) - ]; + const promises = [this.unPinWithName(objectKey)]; delete localDatastore[objectKey]; for (const key in localDatastore) { if (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX)) { let pinned = localDatastore[key] || []; if (pinned.includes(objectKey)) { - pinned = pinned.filter(item => item !== objectKey); + pinned = pinned.filter((item) => item !== objectKey); if (pinned.length == 0) { promises.push(this.unPinWithName(key)); delete localDatastore[key]; @@ -303,7 +304,7 @@ const LocalDatastore = { if (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX)) { let pinned = localDatastore[key] || []; if (pinned.includes(localKey)) { - pinned = pinned.filter(item => item !== localKey); + pinned = pinned.filter((item) => item !== localKey); pinned.push(objectKey); promises.push(this.pinWithName(key, pinned)); localDatastore[key] = pinned; @@ -342,14 +343,14 @@ 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') { - className = '_User'; - objectId = key.split('_')[4]; + if (key.split("_").length === 5 && key.split("_")[3] === "User") { + className = "_User"; + objectId = key.split("_")[4]; } - if (objectId.startsWith('local')) { + if (objectId.startsWith("local")) { continue; } if (!(className in pointersHash)) { @@ -357,14 +358,14 @@ const LocalDatastore = { } pointersHash[className].add(objectId); } - const queryPromises = Object.keys(pointersHash).map(className => { + const queryPromises = Object.keys(pointersHash).map((className) => { const objectIds = Array.from(pointersHash[className]); const query = new ParseQuery(className); query.limit(objectIds.length); if (objectIds.length === 1) { - query.equalTo('objectId', objectIds[0]); + query.equalTo("objectId", objectIds[0]); } else { - query.containedIn('objectId', objectIds); + query.containedIn("objectId", objectIds); } return query.find(); }); @@ -377,8 +378,8 @@ const LocalDatastore = { }); await Promise.all(pinPromises); this.isSyncing = false; - } catch(error) { - console.error('Error syncing LocalDatastore: ', error); + } catch (error) { + console.error("Error syncing LocalDatastore: ", error); this.isSyncing = false; } }, @@ -397,17 +398,21 @@ const LocalDatastore = { checkIfEnabled() { if (!this.isEnabled) { - console.error('Parse.enableLocalDatastore() must be called first'); + console.error("Parse.enableLocalDatastore() must be called first"); } return this.isEnabled; - } + }, }; module.exports = LocalDatastore; -if (process.env.PARSE_BUILD === 'react-native') { - CoreManager.setLocalDatastoreController(require('./LocalDatastoreController.react-native')); +if (process.env.PARSE_BUILD === "react-native") { + CoreManager.setLocalDatastoreController( + require("./LocalDatastoreController.react-native") + ); } else { - CoreManager.setLocalDatastoreController(require('./LocalDatastoreController')); + CoreManager.setLocalDatastoreController( + require("./LocalDatastoreController") + ); } CoreManager.setLocalDatastore(LocalDatastore); diff --git a/src/LocalDatastoreController.js b/src/LocalDatastoreController.js index ca0a5216f..7f0448a42 100644 --- a/src/LocalDatastoreController.js +++ b/src/LocalDatastoreController.js @@ -8,8 +8,8 @@ * * @flow */ -import { isLocalDatastoreKey } from './LocalDatastoreUtils'; -import Storage from './Storage'; +import { isLocalDatastoreKey } from "./LocalDatastoreUtils"; +import Storage from "./Storage"; const LocalDatastoreController = { async fromPinWithName(name: string): Array { @@ -39,7 +39,7 @@ const LocalDatastoreController = { try { LDS[key] = JSON.parse(value); } catch (error) { - console.error('Error getAllContents: ', error); + console.error("Error getAllContents: ", error); } } return LDS; @@ -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..85658b2e9 100644 --- a/src/LocalDatastoreController.react-native.js +++ b/src/LocalDatastoreController.react-native.js @@ -10,8 +10,8 @@ * @private */ -import { isLocalDatastoreKey } from './LocalDatastoreUtils'; -const RNStorage = require('./StorageController.react-native'); +import { isLocalDatastoreKey } from "./LocalDatastoreUtils"; +const RNStorage = require("./StorageController.react-native"); const LocalDatastoreController = { async fromPinWithName(name: string): Promise> { @@ -51,7 +51,7 @@ const LocalDatastoreController = { try { results = await RNStorage.multiGet(batch); } catch (error) { - console.error('Error getAllContents: ', error); + console.error("Error getAllContents: ", error); return {}; } results.forEach((pair) => { @@ -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..2c4b5c9a1 100644 --- a/src/LocalDatastoreUtils.js +++ b/src/LocalDatastoreUtils.js @@ -10,17 +10,17 @@ * @private */ -const DEFAULT_PIN = '_default'; -const PIN_PREFIX = 'parsePin_'; -const OBJECT_PREFIX = 'Parse_LDS_'; +const DEFAULT_PIN = "_default"; +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..e476b0f88 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -9,25 +9,25 @@ * @flow */ -import encode from './encode'; -import ParseFile from './ParseFile'; -import ParseObject from './ParseObject'; -import ParseRelation from './ParseRelation'; -import TaskQueue from './TaskQueue'; -import { RelationOp } from './ParseOp'; +import encode from "./encode"; +import ParseFile from "./ParseFile"; +import ParseObject from "./ParseObject"; +import ParseRelation from "./ParseRelation"; +import TaskQueue from "./TaskQueue"; +import { RelationOp } from "./ParseOp"; -import type { Op } from './ParseOp'; +import type { Op } from "./ParseOp"; export type AttributeMap = { [attr: string]: any }; 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,13 +36,16 @@ export function defaultState(): State { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }; } -export function setServerData(serverData: AttributeMap, attributes: AttributeMap) { +export function setServerData( + serverData: AttributeMap, + attributes: AttributeMap +) { for (const attr in attributes) { - if (typeof attributes[attr] !== 'undefined') { + if (typeof attributes[attr] !== "undefined") { serverData[attr] = attributes[attr]; } else { delete serverData[attr]; @@ -86,7 +89,13 @@ 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]) { @@ -106,7 +115,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) { @@ -123,9 +137,9 @@ export function estimateAttributes(serverData: AttributeMap, pendingOps: Array= 0) { + if (key.indexOf(".") >= 0) { // Key references a subobject - const keyComponents = key.split('.'); + const keyComponents = key.split("."); const subObjectKey = keyComponents[0]; - const keyRemainder = keyComponents.slice(1).join('.'); - return matchesKeyConstraints(className, object[subObjectKey] || {}, objects, keyRemainder, constraints); + const keyRemainder = keyComponents.slice(1).join("."); + return matchesKeyConstraints( + className, + object[subObjectKey] || {}, + objects, + keyRemainder, + constraints + ); } let i; - if (key === '$or') { + if (key === "$or") { for (i = 0; i < constraints.length; i++) { if (matchesQuery(className, object, objects, constraints[i])) { return true; @@ -111,7 +124,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - if (key === '$and') { + if (key === "$and") { for (i = 0; i < constraints.length; i++) { if (!matchesQuery(className, object, objects, constraints[i])) { return false; @@ -119,7 +132,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - if (key === '$nor') { + if (key === "$nor") { for (i = 0; i < constraints.length; i++) { if (matchesQuery(className, object, objects, constraints[i])) { return false; @@ -127,15 +140,15 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - if (key === '$relatedTo') { + if (key === "$relatedTo") { // Bail! We can't handle relational queries locally return false; } - if (!(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) { + if (!/^[A-Za-z][0-9A-Za-z_]*$/.test(key)) { throw new ParseError(ParseError.INVALID_KEY_NAME, `Invalid Key: ${key}`); } // Equality (or Array contains) cases - if (typeof constraints !== 'object') { + if (typeof constraints !== "object") { if (Array.isArray(object[key])) { return object[key].indexOf(constraints) > -1; } @@ -143,12 +156,20 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } let compareTo; if (constraints.__type) { - if (constraints.__type === 'Pointer') { + if (constraints.__type === "Pointer") { return equalObjectsGeneric(object[key], constraints, function (obj, ptr) { - return typeof obj !== 'undefined' && ptr.className === obj.className && ptr.objectId === obj.objectId; + return ( + typeof obj !== "undefined" && + ptr.className === obj.className && + ptr.objectId === obj.objectId + ); }); } - return equalObjectsGeneric(decode(object[key]), decode(constraints), equalObjects); + return equalObjectsGeneric( + decode(object[key]), + decode(constraints), + equalObjects + ); } // More complex cases for (const condition in constraints) { @@ -157,90 +178,97 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { compareTo = decode(compareTo); } // Compare Date Object or Date String - if (toString.call(compareTo) === '[object Date]' || - (typeof compareTo === 'string' && - new Date(compareTo) !== 'Invalid Date' && - !isNaN(new Date(compareTo)))) { + if ( + toString.call(compareTo) === "[object Date]" || + (typeof compareTo === "string" && + new Date(compareTo) !== "Invalid Date" && + !isNaN(new Date(compareTo))) + ) { object[key] = new Date(object[key].iso ? object[key].iso : object[key]); } switch (condition) { - case '$lt': + case "$lt": if (object[key] >= compareTo) { return false; } break; - case '$lte': + case "$lte": if (object[key] > compareTo) { return false; } break; - case '$gt': + case "$gt": if (object[key] <= compareTo) { return false; } break; - case '$gte': + case "$gte": if (object[key] < compareTo) { return false; } break; - case '$ne': + case "$ne": if (equalObjects(object[key], compareTo)) { return false; } break; - case '$in': + case "$in": if (!contains(compareTo, object[key])) { return false; } break; - case '$nin': + case "$nin": if (contains(compareTo, object[key])) { return false; } break; - case '$all': + case "$all": for (i = 0; i < compareTo.length; i++) { if (object[key].indexOf(compareTo[i]) < 0) { return false; } } break; - case '$exists': - { - const propertyExists = typeof object[key] !== 'undefined'; - const existenceIsRequired = constraints['$exists']; - if (typeof constraints['$exists'] !== 'boolean') { + case "$exists": { + const propertyExists = typeof object[key] !== "undefined"; + const existenceIsRequired = constraints["$exists"]; + if (typeof constraints["$exists"] !== "boolean") { // The SDK will never submit a non-boolean for $exists, but if someone // tries to submit a non-boolean for $exits outside the SDKs, just ignore it. break; } - if (!propertyExists && existenceIsRequired || propertyExists && !existenceIsRequired) { + if ( + (!propertyExists && existenceIsRequired) || + (propertyExists && !existenceIsRequired) + ) { return false; } break; } - case '$regex': { - if (typeof compareTo === 'object') { + case "$regex": { + if (typeof compareTo === "object") { return compareTo.test(object[key]); } // JS doesn't support perl-style escaping - let expString = ''; + let expString = ""; let escapeEnd = -2; - let escapeStart = compareTo.indexOf('\\Q'); + let escapeStart = compareTo.indexOf("\\Q"); while (escapeStart > -1) { // Add the unescaped portion expString += compareTo.substring(escapeEnd + 2, escapeStart); - escapeEnd = compareTo.indexOf('\\E', escapeStart); + escapeEnd = compareTo.indexOf("\\E", escapeStart); if (escapeEnd > -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); + escapeStart = compareTo.indexOf("\\Q", escapeEnd); } expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2)); - let modifiers = constraints.$options || ''; - modifiers = modifiers.replace('x', '').replace('s', '') + let modifiers = constraints.$options || ""; + 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])) { @@ -248,7 +276,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } break; } - case '$nearSphere': { + case "$nearSphere": { if (!compareTo || !object[key]) { return false; } @@ -256,29 +284,42 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { const max = constraints.$maxDistance || Infinity; return distance <= max; } - case '$within': { + case "$within": { if (!compareTo || !object[key]) { return false; } const southWest = compareTo.$box[0]; const northEast = compareTo.$box[1]; - if (southWest.latitude > northEast.latitude || southWest.longitude > northEast.longitude) { + if ( + southWest.latitude > northEast.latitude || + southWest.longitude > northEast.longitude + ) { // 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': + case "$options": // Not a query type, but a way to add options to $regex. Ignore and // avoid the default break; - case '$maxDistance': + case "$maxDistance": // Not a query type, but a way to add a cap to $nearSphere. Ignore and // avoid the default break; - case '$select': { + case "$select": { const subQueryObjects = objects.filter((obj, index, arr) => { - return matchesQuery(compareTo.query.className, obj, arr, compareTo.query.where); + return matchesQuery( + compareTo.query.className, + obj, + arr, + compareTo.query.where + ); }); for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); @@ -286,9 +327,14 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - case '$dontSelect': { + case "$dontSelect": { const subQueryObjects = objects.filter((obj, index, arr) => { - return matchesQuery(compareTo.query.className, obj, arr, compareTo.query.where); + return matchesQuery( + compareTo.query.className, + obj, + arr, + compareTo.query.where + ); }); for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); @@ -296,35 +342,39 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - case '$inQuery': { + case "$inQuery": { const subQueryObjects = objects.filter((obj, index, arr) => { return matchesQuery(compareTo.className, obj, arr, compareTo.where); }); 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; } } return false; } - case '$notInQuery': { + case "$notInQuery": { const subQueryObjects = objects.filter((obj, index, arr) => { return matchesQuery(compareTo.className, obj, arr, compareTo.where); }); 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; } } return true; } - case '$containedBy': { + case "$containedBy": { for (const value of object[key]) { if (!contains(compareTo, value)) { return false; @@ -332,12 +382,15 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - case '$geoWithin': { - const points = compareTo.$polygon.map((geoPoint) => [geoPoint.latitude, geoPoint.longitude]); + case "$geoWithin": { + const points = compareTo.$polygon.map((geoPoint) => [ + geoPoint.latitude, + geoPoint.longitude, + ]); const polygon = new ParsePolygon(points); return polygon.containsPoint(object[key]); } - case '$geoIntersects': { + case "$geoIntersects": { const polygon = new ParsePolygon(object[key].coordinates); const point = new ParseGeoPoint(compareTo.$point); return polygon.containsPoint(point); @@ -355,18 +408,38 @@ 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 => { + Object.keys(q).forEach((key) => { if (q && q[key] && q[key].$regex) { - if (typeof q[key].$options === 'string') { + 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}` + ); } } } - if (specialQuerykeys.indexOf(key) < 0 && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { - throw new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: ${key}`); + if ( + specialQuerykeys.indexOf(key) < 0 && + !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/) + ) { + throw new ParseError( + ParseError.INVALID_KEY_NAME, + `Invalid key name: ${key}` + ); } }); } diff --git a/src/Parse.js b/src/Parse.js index 7fd2db52e..431c2dd3f 100644 --- a/src/Parse.js +++ b/src/Parse.js @@ -7,13 +7,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import decode from './decode'; -import encode from './encode'; -import CoreManager from './CoreManager'; -import CryptoController from './CryptoController'; -import InstallationController from './InstallationController'; -import * as ParseOp from './ParseOp'; -import RESTController from './RESTController'; +import decode from "./decode"; +import encode from "./encode"; +import CoreManager from "./CoreManager"; +import CryptoController from "./CryptoController"; +import InstallationController from "./InstallationController"; +import * as ParseOp from "./ParseOp"; +import RESTController from "./RESTController"; /** * Contains all Parse API classes and functions. @@ -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 */ } @@ -45,10 +49,10 @@ const Parse = { }, _initialize(applicationId: string, javaScriptKey: string, masterKey: string) { - CoreManager.set('APPLICATION_ID', applicationId); - CoreManager.set('JAVASCRIPT_KEY', javaScriptKey); - CoreManager.set('MASTER_KEY', masterKey); - CoreManager.set('USE_MASTER_KEY', false); + CoreManager.set("APPLICATION_ID", applicationId); + CoreManager.set("JAVASCRIPT_KEY", javaScriptKey); + CoreManager.set("MASTER_KEY", masterKey); + CoreManager.set("USE_MASTER_KEY", false); }, /** @@ -79,10 +83,10 @@ const Parse = { * @static */ set applicationId(value) { - CoreManager.set('APPLICATION_ID', value); + CoreManager.set("APPLICATION_ID", value); }, get applicationId() { - return CoreManager.get('APPLICATION_ID'); + return CoreManager.get("APPLICATION_ID"); }, /** @@ -90,10 +94,10 @@ const Parse = { * @static */ set javaScriptKey(value) { - CoreManager.set('JAVASCRIPT_KEY', value); + CoreManager.set("JAVASCRIPT_KEY", value); }, get javaScriptKey() { - return CoreManager.get('JAVASCRIPT_KEY'); + return CoreManager.get("JAVASCRIPT_KEY"); }, /** @@ -101,10 +105,10 @@ const Parse = { * @static */ set masterKey(value) { - CoreManager.set('MASTER_KEY', value); + CoreManager.set("MASTER_KEY", value); }, get masterKey() { - return CoreManager.get('MASTER_KEY'); + return CoreManager.get("MASTER_KEY"); }, /** @@ -112,10 +116,10 @@ const Parse = { * @static */ set serverURL(value) { - CoreManager.set('SERVER_URL', value); + CoreManager.set("SERVER_URL", value); }, get serverURL() { - return CoreManager.get('SERVER_URL'); + return CoreManager.get("SERVER_URL"); }, /** @@ -123,10 +127,10 @@ const Parse = { * @static */ set serverAuthToken(value) { - CoreManager.set('SERVER_AUTH_TOKEN', value); + CoreManager.set("SERVER_AUTH_TOKEN", value); }, get serverAuthToken() { - return CoreManager.get('SERVER_AUTH_TOKEN'); + return CoreManager.get("SERVER_AUTH_TOKEN"); }, /** @@ -134,10 +138,10 @@ const Parse = { * @static */ set serverAuthType(value) { - CoreManager.set('SERVER_AUTH_TYPE', value); + CoreManager.set("SERVER_AUTH_TYPE", value); }, get serverAuthType() { - return CoreManager.get('SERVER_AUTH_TYPE'); + return CoreManager.get("SERVER_AUTH_TYPE"); }, /** @@ -145,10 +149,10 @@ const Parse = { * @static */ set liveQueryServerURL(value) { - CoreManager.set('LIVEQUERY_SERVER_URL', value); + CoreManager.set("LIVEQUERY_SERVER_URL", value); }, get liveQueryServerURL() { - return CoreManager.get('LIVEQUERY_SERVER_URL'); + return CoreManager.get("LIVEQUERY_SERVER_URL"); }, /** @@ -156,10 +160,10 @@ const Parse = { * @static */ set encryptedUser(value) { - CoreManager.set('ENCRYPTED_USER', value); + CoreManager.set("ENCRYPTED_USER", value); }, get encryptedUser() { - return CoreManager.get('ENCRYPTED_USER'); + return CoreManager.get("ENCRYPTED_USER"); }, /** @@ -167,10 +171,10 @@ const Parse = { * @static */ set secret(value) { - CoreManager.set('ENCRYPTED_KEY', value); + CoreManager.set("ENCRYPTED_KEY", value); }, get secret() { - return CoreManager.get('ENCRYPTED_KEY'); + return CoreManager.get("ENCRYPTED_KEY"); }, /** @@ -178,27 +182,27 @@ const Parse = { * @static */ set idempotency(value) { - CoreManager.set('IDEMPOTENCY', value); + CoreManager.set("IDEMPOTENCY", value); }, get idempotency() { - return CoreManager.get('IDEMPOTENCY'); + return CoreManager.get("IDEMPOTENCY"); }, }; -Parse.ACL = require('./ParseACL').default; -Parse.Analytics = require('./Analytics'); -Parse.AnonymousUtils = require('./AnonymousUtils').default; -Parse.Cloud = require('./Cloud'); -Parse.CoreManager = require('./CoreManager'); -Parse.Config = require('./ParseConfig').default; -Parse.Error = require('./ParseError').default; -Parse.FacebookUtils = require('./FacebookUtils').default; -Parse.File = require('./ParseFile').default; -Parse.GeoPoint = require('./ParseGeoPoint').default; -Parse.Polygon = require('./ParsePolygon').default; -Parse.Installation = require('./ParseInstallation').default; -Parse.LocalDatastore = require('./LocalDatastore'); -Parse.Object = require('./ParseObject').default; +Parse.ACL = require("./ParseACL").default; +Parse.Analytics = require("./Analytics"); +Parse.AnonymousUtils = require("./AnonymousUtils").default; +Parse.Cloud = require("./Cloud"); +Parse.CoreManager = require("./CoreManager"); +Parse.Config = require("./ParseConfig").default; +Parse.Error = require("./ParseError").default; +Parse.FacebookUtils = require("./FacebookUtils").default; +Parse.File = require("./ParseFile").default; +Parse.GeoPoint = require("./ParseGeoPoint").default; +Parse.Polygon = require("./ParsePolygon").default; +Parse.Installation = require("./ParseInstallation").default; +Parse.LocalDatastore = require("./LocalDatastore"); +Parse.Object = require("./ParseObject").default; Parse.Op = { Set: ParseOp.SetOp, Unset: ParseOp.UnsetOp, @@ -206,53 +210,53 @@ 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; -Parse.Relation = require('./ParseRelation').default; -Parse.Role = require('./ParseRole').default; -Parse.Schema = require('./ParseSchema').default; -Parse.Session = require('./ParseSession').default; -Parse.Storage = require('./Storage'); -Parse.User = require('./ParseUser').default; -Parse.LiveQuery = require('./ParseLiveQuery').default; -Parse.LiveQueryClient = require('./LiveQueryClient').default; +Parse.Push = require("./Push"); +Parse.Query = require("./ParseQuery").default; +Parse.Relation = require("./ParseRelation").default; +Parse.Role = require("./ParseRole").default; +Parse.Schema = require("./ParseSchema").default; +Parse.Session = require("./ParseSession").default; +Parse.Storage = require("./Storage"); +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 + 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,21 +292,21 @@ Parse.enableEncryptedUser = function() { * @static * @returns {boolean} */ -Parse.isEncryptedUserEnabled = function() { +Parse.isEncryptedUserEnabled = function () { return Parse.encryptedUser; -} +}; CoreManager.setCryptoController(CryptoController); CoreManager.setInstallationController(InstallationController); CoreManager.setRESTController(RESTController); -if (process.env.PARSE_BUILD === 'node') { +if (process.env.PARSE_BUILD === "node") { Parse.initialize = Parse._initialize; Parse.Cloud = Parse.Cloud || {}; - Parse.Cloud.useMasterKey = function() { - CoreManager.set('USE_MASTER_KEY', true); - } - Parse.Hooks = require('./ParseHooks'); + Parse.Cloud.useMasterKey = function () { + CoreManager.set("USE_MASTER_KEY", true); + }; + Parse.Hooks = require("./ParseHooks"); } // For legacy requires, of the form `var Parse = require('parse').Parse` diff --git a/src/ParseACL.js b/src/ParseACL.js index c756fec25..00e38ee70 100644 --- a/src/ParseACL.js +++ b/src/ParseACL.js @@ -9,13 +9,13 @@ * @flow */ -import ParseRole from './ParseRole'; -import ParseUser from './ParseUser'; +import ParseRole from "./ParseRole"; +import ParseUser from "./ParseUser"; type PermissionsMap = { [permission: string]: boolean }; type ByIdMap = { [userId: string]: PermissionsMap }; -const PUBLIC_KEY = '*'; +const PUBLIC_KEY = "*"; /** * Creates a new ACL. @@ -39,7 +39,7 @@ class ParseACL { */ constructor(arg1: ParseUser | ByIdMap) { this.permissionsById = {}; - if (arg1 && typeof arg1 === 'object') { + if (arg1 && typeof arg1 === "object") { if (arg1 instanceof ParseUser) { this.setReadAccess(arg1, true); this.setWriteAccess(arg1, true); @@ -49,23 +49,23 @@ class ParseACL { this.permissionsById[userId] = {}; for (const permission in accessList) { const allowed = accessList[permission]; - if (permission !== 'read' && permission !== 'write') { + if (permission !== "read" && permission !== "write") { throw new TypeError( - 'Tried to create an ACL with an invalid permission type.' + "Tried to create an ACL with an invalid permission type." ); } - if (typeof allowed !== 'boolean') { + if (typeof allowed !== "boolean") { throw new TypeError( - 'Tried to create an ACL with an invalid permission value.' + "Tried to create an ACL with an invalid permission value." ); } this.permissionsById[userId][permission] = allowed; } } } - } else if (typeof arg1 === 'function') { + } else if (typeof arg1 === "function") { throw new TypeError( - 'ParseACL constructed with a function. Did you forget ()?' + "ParseACL constructed with a function. Did you forget ()?" ); } } @@ -112,21 +112,25 @@ class ParseACL { return true; } - _setAccess(accessType: string, userId: ParseUser | ParseRole | string, allowed: boolean) { + _setAccess( + accessType: string, + userId: ParseUser | ParseRole | string, + allowed: boolean + ) { if (userId instanceof ParseUser) { userId = userId.id; } else if (userId instanceof ParseRole) { const name = userId.getName(); if (!name) { - throw new TypeError('Role must have a name'); + throw new TypeError("Role must have a name"); } - userId = 'role:' + name; + userId = "role:" + name; } - if (typeof userId !== 'string') { - throw new TypeError('userId must be a string.'); + if (typeof userId !== "string") { + throw new TypeError("userId must be a string."); } - if (typeof allowed !== 'boolean') { - throw new TypeError('allowed must be either true or false.'); + if (typeof allowed !== "boolean") { + throw new TypeError("allowed must be either true or false."); } let permissions = this.permissionsById[userId]; if (!permissions) { @@ -156,14 +160,14 @@ class ParseACL { if (userId instanceof ParseUser) { userId = userId.id; if (!userId) { - throw new Error('Cannot get access for a ParseUser without an ID'); + throw new Error("Cannot get access for a ParseUser without an ID"); } } else if (userId instanceof ParseRole) { const name = userId.getName(); if (!name) { - throw new TypeError('Role must have a name'); + throw new TypeError("Role must have a name"); } - userId = 'role:' + name; + userId = "role:" + name; } const permissions = this.permissionsById[userId]; if (!permissions) { @@ -179,7 +183,7 @@ class ParseACL { * @param {boolean} allowed Whether that user should have read access. */ setReadAccess(userId: ParseUser | ParseRole | string, allowed: boolean) { - this._setAccess('read', userId, allowed); + this._setAccess("read", userId, allowed); } /** @@ -192,7 +196,7 @@ class ParseACL { * @returns {boolean} */ getReadAccess(userId: ParseUser | ParseRole | string): boolean { - return this._getAccess('read', userId); + return this._getAccess("read", userId); } /** @@ -202,7 +206,7 @@ class ParseACL { * @param {boolean} allowed Whether that user should have write access. */ setWriteAccess(userId: ParseUser | ParseRole | string, allowed: boolean) { - this._setAccess('write', userId, allowed); + this._setAccess("write", userId, allowed); } /** @@ -215,7 +219,7 @@ class ParseACL { * @returns {boolean} */ getWriteAccess(userId: ParseUser | ParseRole | string): boolean { - return this._getAccess('write', userId); + return this._getAccess("write", userId); } /** @@ -268,12 +272,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + if (typeof role !== "string") { + throw new TypeError("role must be a ParseRole or a String"); } - return this.getReadAccess('role:' + role); + return this.getReadAccess("role:" + role); } /** @@ -290,12 +292,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + if (typeof role !== "string") { + throw new TypeError("role must be a ParseRole or a String"); } - return this.getWriteAccess('role:' + role); + return this.getWriteAccess("role:" + role); } /** @@ -311,12 +311,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + if (typeof role !== "string") { + throw new TypeError("role must be a ParseRole or a String"); } - this.setReadAccess('role:' + role, allowed); + this.setReadAccess("role:" + role, allowed); } /** @@ -332,12 +330,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + if (typeof role !== "string") { + throw new TypeError("role must be a ParseRole or a String"); } - this.setWriteAccess('role:' + role, allowed); + this.setWriteAccess("role:" + role, allowed); } } diff --git a/src/ParseConfig.js b/src/ParseConfig.js index ebd11883b..9d0e0a9e3 100644 --- a/src/ParseConfig.js +++ b/src/ParseConfig.js @@ -9,14 +9,14 @@ * @flow */ -import CoreManager from './CoreManager'; -import decode from './decode'; -import encode from './encode'; -import escape from './escape'; -import ParseError from './ParseError'; -import Storage from './Storage'; +import CoreManager from "./CoreManager"; +import decode from "./decode"; +import encode from "./encode"; +import escape from "./escape"; +import ParseError from "./ParseError"; +import Storage from "./Storage"; -import type { RequestOptions } from './RESTController'; +import type { RequestOptions } from "./RESTController"; /** * Parse.Config is a local representation of configuration data that @@ -56,7 +56,7 @@ class ParseConfig { return html; } const val = this.attributes[attr]; - let escaped = ''; + let escaped = ""; if (val != null) { escaped = escape(val.toString()); } @@ -107,14 +107,20 @@ class ParseConfig { * @returns {Promise} A promise that is resolved with a newly-created * configuration object or with the current with the update. */ - static save(attrs: { [key: string]: any }, masterKeyOnlyFlags: { [key: string]: any }) { + 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); + } + ); } /** @@ -129,15 +135,15 @@ class ParseConfig { let currentConfig = null; -const CURRENT_CONFIG_KEY = 'currentConfig'; +const CURRENT_CONFIG_KEY = "currentConfig"; function decodePayload(data) { try { const json = JSON.parse(data); - if (json && typeof json === 'object') { + if (json && typeof json === "object") { return decode(json); } - } catch(e) { + } catch (e) { return null; } } @@ -178,55 +184,58 @@ const DefaultController = { get(options: RequestOptions = {}) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'config', {}, options - ).then((response) => { - if (!response || !response.params) { - const error = new ParseError( - ParseError.INVALID_JSON, - 'Config JSON response invalid.' - ); - return Promise.reject(error); - } + return RESTController.request("GET", "config", {}, options).then( + (response) => { + if (!response || !response.params) { + const error = new ParseError( + ParseError.INVALID_JSON, + "Config JSON response invalid." + ); + return Promise.reject(error); + } - const config = new ParseConfig(); - config.attributes = {}; - for (const attr in response.params) { - config.attributes[attr] = decode(response.params[attr]); + const config = new ParseConfig(); + config.attributes = {}; + for (const attr in response.params) { + config.attributes[attr] = decode(response.params[attr]); + } + currentConfig = config; + return Storage.setItemAsync( + Storage.generatePath(CURRENT_CONFIG_KEY), + JSON.stringify(response.params) + ).then(() => { + return config; + }); } - currentConfig = config; - return Storage.setItemAsync( - Storage.generatePath(CURRENT_CONFIG_KEY), - JSON.stringify(response.params) - ).then(() => { - return config; - }); - }); + ); }, - save(attrs: { [key: string]: any }, masterKeyOnlyFlags: { [key: string]: any }) { + 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', - 'config', + "PUT", + "config", { params: encodedAttrs, masterKeyOnly: masterKeyOnlyFlags }, { useMasterKey: true } - ).then(response => { - if(response && response.result){ - return Promise.resolve() + ).then((response) => { + if (response && response.result) { + return Promise.resolve(); } else { const error = new ParseError( ParseError.INTERNAL_SERVER_ERROR, - 'Error occured updating Config.' + "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..59e876344 100644 --- a/src/ParseError.js +++ b/src/ParseError.js @@ -20,14 +20,14 @@ class ParseError extends Error { constructor(code, message) { super(message); this.code = code; - Object.defineProperty(this, 'message', { + Object.defineProperty(this, "message", { enumerable: true, - value: message + value: message, }); } toString() { - return 'ParseError: ' + this.code + ' ' + this.message; + return "ParseError: " + this.code + " " + this.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..0b8fbb695 100644 --- a/src/ParseFile.js +++ b/src/ParseFile.js @@ -9,38 +9,40 @@ * @flow */ /* global XMLHttpRequest, Blob */ -import CoreManager from './CoreManager'; -import type { FullOptions } from './RESTController'; +import CoreManager from "./CoreManager"; +import type { FullOptions } from "./RESTController"; -const ParseError = require('./ParseError').default; +const ParseError = require("./ParseError").default; let XHR = null; -if (typeof XMLHttpRequest !== 'undefined') { +if (typeof XMLHttpRequest !== "undefined") { XHR = XMLHttpRequest; } -if (process.env.PARSE_BUILD === 'weapp') { - XHR = require('./Xhr.weapp'); +if (process.env.PARSE_BUILD === "weapp") { + XHR = require("./Xhr.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) { @@ -53,12 +55,12 @@ function b64Digit(number: number): string { return String.fromCharCode(48 + (number - 52)); } if (number === 62) { - return '+'; + return "+"; } if (number === 63) { - return '/'; + return "/"; } - throw new TypeError('Tried to encode large digit ' + number + ' in base64.'); + throw new TypeError("Tried to encode large digit " + number + " in base64."); } /** @@ -107,8 +109,14 @@ class ParseFile { * @param metadata {Object} Optional key value pairs to be stored with file object * @param tags {Object} Optional key value pairs to be stored with file object */ - constructor(name: string, data?: FileData, type?: string, metadata?: Object, tags?: Object) { - const specifiedType = type || ''; + constructor( + name: string, + data?: FileData, + type?: string, + metadata?: Object, + tags?: Object + ) { + const specifiedType = type || ""; this._name = name; this._metadata = metadata || {}; @@ -118,45 +126,49 @@ class ParseFile { if (Array.isArray(data)) { this._data = ParseFile.encodeBase64(data); this._source = { - format: 'base64', + format: "base64", base64: this._data, - type: specifiedType + type: specifiedType, }; - } else if (typeof Blob !== 'undefined' && data instanceof Blob) { + } else if (typeof Blob !== "undefined" && data instanceof Blob) { this._source = { - format: 'file', + format: "file", file: data, - type: specifiedType + type: specifiedType, }; - } else if (data && typeof data.uri === 'string' && data.uri !== undefined) { + } else if ( + data && + typeof data.uri === "string" && + data.uri !== undefined + ) { this._source = { - format: 'uri', + format: "uri", uri: data.uri, - type: specifiedType + type: specifiedType, }; - } else if (data && typeof data.base64 === 'string') { + } else if (data && typeof data.base64 === "string") { const base64 = data.base64; - const commaIndex = base64.indexOf(','); + const commaIndex = base64.indexOf(","); if (commaIndex !== -1) { const matches = dataUriRegexp.exec(base64.slice(0, commaIndex + 1)); // if data URI with type and charset, there will be 4 matches. this._data = base64.slice(commaIndex + 1); this._source = { - format: 'base64', + format: "base64", base64: this._data, - type: matches[1] + type: matches[1], }; } else { this._data = base64; this._source = { - format: 'base64', + format: "base64", base64: base64, - type: specifiedType + type: specifiedType, }; } } else { - throw new TypeError('Cannot create a Parse.File with that data.'); + throw new TypeError("Cannot create a Parse.File with that data."); } } } @@ -173,10 +185,10 @@ class ParseFile { return this._data; } if (!this._url) { - throw new Error('Cannot retrieve data for unsaved 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); @@ -208,7 +220,7 @@ class ParseFile { return; } if (options.forceSecure) { - return this._url.replace(/^http:\/\//i, 'https://'); + return this._url.replace(/^http:\/\//i, "https://"); } else { return this._url; } @@ -257,46 +269,53 @@ 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._name = res.name; - this._url = res.url; - this._data = null; - this._requestTask = null; - 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; - }); + if (this._source.format === "file") { + this._previousSave = controller + .saveFile(this._name, this._source, options) + .then((res) => { + this._name = res.name; + this._url = res.url; + this._data = null; + this._requestTask = null; + 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; + }); } else { - this._previousSave = controller.saveBase64(this._name, this._source, options).then((res) => { - this._name = res.name; - this._url = res.url; - this._requestTask = null; - return this; - }); + this._previousSave = controller + .saveBase64(this._name, this._source, options) + .then((res) => { + this._name = res.name; + this._url = res.url; + this._requestTask = null; + return this; + }); } } if (this._previousSave) { @@ -308,7 +327,7 @@ class ParseFile { * Aborts the request if it has already been sent. */ cancel() { - if (this._requestTask && typeof this._requestTask.abort === 'function') { + if (this._requestTask && typeof this._requestTask.abort === "function") { this._requestTask.abort(); } this._requestTask = null; @@ -322,7 +341,10 @@ class ParseFile { */ destroy() { if (!this._name) { - throw new ParseError(ParseError.FILE_DELETE_UNNAMED_ERROR, 'Cannot delete an unnamed file.'); + throw new ParseError( + ParseError.FILE_DELETE_UNNAMED_ERROR, + "Cannot delete an unnamed file." + ); } const controller = CoreManager.getFileController(); return controller.deleteFile(this._name).then(() => { @@ -334,9 +356,9 @@ class ParseFile { toJSON(): { name: ?string, url: ?string } { return { - __type: 'File', + __type: "File", name: this._name, - url: this._url + url: this._url, }; } @@ -346,10 +368,10 @@ 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' + typeof this.url() !== "undefined" ); } @@ -359,7 +381,7 @@ class ParseFile { * @param {object} metadata Key value pairs to be stored with file object */ setMetadata(metadata: any) { - if (metadata && typeof metadata === 'object') { + if (metadata && typeof metadata === "object") { Object.keys(metadata).forEach((key) => { this.addMetadata(key, metadata[key]); }); @@ -373,7 +395,7 @@ class ParseFile { * @param {*} value metadata */ addMetadata(key: string, value: any) { - if (typeof key === 'string') { + if (typeof key === "string") { this._metadata[key] = value; } } @@ -384,7 +406,7 @@ class ParseFile { * @param {object} tags Key value pairs to be stored with file object */ setTags(tags: any) { - if (tags && typeof tags === 'object') { + if (tags && typeof tags === "object") { Object.keys(tags).forEach((key) => { this.addTag(key, tags[key]); }); @@ -398,14 +420,14 @@ class ParseFile { * @param {*} value tag */ addTag(key: string, value: string) { - if (typeof key === 'string') { + if (typeof key === "string") { this._tags[key] = value; } } static fromJSON(obj): ParseFile { - if (obj.__type !== 'File') { - throw new TypeError('JSON object does not represent a ParseFile'); + if (obj.__type !== "File") { + throw new TypeError("JSON object does not represent a ParseFile"); } const file = new ParseFile(obj.name); file._url = obj.url; @@ -420,52 +442,60 @@ 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) : '=' - ].join(''); + b64Digit((b1 >> 2) & 0x3f), + b64Digit(((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0f)), + has2 ? b64Digit(((b2 << 2) & 0x3c) | ((b3 >> 6) & 0x03)) : "=", + has3 ? b64Digit(b3 & 0x3f) : "=", + ].join(""); } - return chunks.join(''); + return chunks.join(""); } } const DefaultController = { - 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.'); + 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."); } const base64Data = await new Promise((res, rej) => { // eslint-disable-next-line no-undef const reader = new FileReader(); reader.onload = () => res(reader.result); - reader.onerror = error => rej(error); + reader.onerror = (error) => rej(error); reader.readAsDataURL(source.file); }); // we only want the data after the comma // For example: "data:application/pdf;base64,JVBERi0xLjQKJ..." we would only want "JVBERi0xLjQKJ..." - const [first, second] = base64Data.split(','); + const [first, second] = base64Data.split(","); // in the event there is no 'data:application/pdf;base64,' at the beginning of the base64 string // use the entire string instead const data = second ? second : first; const newSource = { - format: 'base64', + format: "base64", base64: data, type: source.type || (source.file ? source.file.type : null), }; return await DefaultController.saveBase64(name, newSource, options); }, - saveBase64: function(name: string, source: FileSource, options?: FullOptions) { - if (source.format !== 'base64') { - throw new Error('saveBase64 can only be used with Base64-type sources.'); + 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 }, @@ -477,47 +507,50 @@ const DefaultController = { if (source.type) { data._ContentType = source.type; } - const path = 'files/' + name; - return CoreManager.getRESTController().request('POST', path, data, options); + const path = "files/" + name; + 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') { + } else if (process.env.PARSE_BUILD === "node") { return new Promise((resolve, reject) => { - const client = uri.indexOf('https') === 0 - ? require('https') - : require('http'); + 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('end', () => { + resp.setEncoding("base64"); + let base64 = ""; + resp.on("data", (data) => (base64 += data)); + resp.on("end", () => { resolve({ base64, - contentType: resp.headers['content-type'], + contentType: resp.headers["content-type"], }); }); }); - req.on('abort', () => { + req.on("abort", () => { resolve({}); }); - req.on('error', reject); + req.on("error", reject); options.requestTask(req); }); } else { - return Promise.reject('Cannot make a request: No definition of XMLHttpRequest was found.'); + return Promise.reject( + "Cannot make a request: No definition of XMLHttpRequest was found." + ); } }, - 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.open("GET", uri, true); + xhr.responseType = "arraybuffer"; + xhr.onerror = function (e) { + reject(e); + }; + xhr.onreadystatechange = function () { if (xhr.readyState !== xhr.DONE) { return; } @@ -527,7 +560,7 @@ const DefaultController = { const bytes = new Uint8Array(this.response); resolve({ base64: ParseFile.encodeBase64(bytes), - contentType: xhr.getResponseHeader('content-type'), + contentType: xhr.getResponseHeader("content-type"), }); }; options.requestTask(xhr); @@ -535,24 +568,29 @@ 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'), + "X-Parse-Application-ID": CoreManager.get("APPLICATION_ID"), + "X-Parse-Master-Key": CoreManager.get("MASTER_KEY"), }; - let url = CoreManager.get('SERVER_URL'); - if (url[url.length - 1] !== '/') { - url += '/'; + let url = CoreManager.get("SERVER_URL"); + if (url[url.length - 1] !== "/") { + 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); - } - }); + 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); + } + }); }, _setXHR(xhr: any) { diff --git a/src/ParseGeoPoint.js b/src/ParseGeoPoint.js index 71cb1f99b..8d9006534 100644 --- a/src/ParseGeoPoint.js +++ b/src/ParseGeoPoint.js @@ -42,15 +42,14 @@ 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]); this._latitude = arg1[0]; this._longitude = arg1[1]; - } else if (typeof arg1 === 'object') { + } else if (typeof arg1 === "object") { ParseGeoPoint._validate(arg1.latitude, arg1.longitude); this._latitude = arg1.latitude; this._longitude = arg1.longitude; @@ -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', + __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,12 @@ 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,31 +169,33 @@ 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' + "GeoPoint latitude and longitude must be valid numbers" ); } if (latitude < -90.0) { throw new TypeError( - 'GeoPoint latitude out of bounds: ' + latitude + ' < -90.0.' + "GeoPoint latitude out of bounds: " + latitude + " < -90.0." ); } if (latitude > 90.0) { throw new TypeError( - 'GeoPoint latitude out of bounds: ' + latitude + ' > 90.0.' + "GeoPoint latitude out of bounds: " + latitude + " > 90.0." ); } if (longitude < -180.0) { throw new TypeError( - 'GeoPoint longitude out of bounds: ' + longitude + ' < -180.0.' + "GeoPoint longitude out of bounds: " + longitude + " < -180.0." ); } if (longitude > 180.0) { throw new TypeError( - 'GeoPoint longitude out of bounds: ' + longitude + ' > 180.0.' + "GeoPoint longitude out of bounds: " + longitude + " > 180.0." ); } } @@ -204,7 +208,10 @@ class ParseGeoPoint { */ static current() { return navigator.geolocation.getCurrentPosition((location) => { - return new ParseGeoPoint(location.coords.latitude, location.coords.longitude); + return new ParseGeoPoint( + location.coords.latitude, + location.coords.longitude + ); }); } } diff --git a/src/ParseHooks.js b/src/ParseHooks.js index 9637261de..f9d93b8fd 100644 --- a/src/ParseHooks.js +++ b/src/ParseHooks.js @@ -1,12 +1,12 @@ -import CoreManager from './CoreManager'; -import decode from './decode'; -import ParseError from './ParseError'; +import CoreManager from "./CoreManager"; +import decode from "./decode"; +import ParseError from "./ParseError"; export function getFunctions() { return CoreManager.getHooksController().get("functions"); } -export function getTriggers() { +export function getTriggers() { return CoreManager.getHooksController().get("triggers"); } @@ -15,15 +15,19 @@ export function getFunction(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 +35,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 +47,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,10 +59,9 @@ export function remove(hook) { } const DefaultController = { - get(type, functionName, triggerName) { let url = "/hooks/" + type; - if(functionName) { + if (functionName) { url += "/" + functionName; if (triggerName) { url += "/" + triggerName; @@ -74,7 +77,7 @@ const DefaultController = { } else if (hook.className && hook.triggerName && hook.url) { 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); }, @@ -89,9 +92,9 @@ const DefaultController = { 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) { @@ -104,25 +107,27 @@ const DefaultController = { 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); + 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..2fd45b00d 100644 --- a/src/ParseInstallation.js +++ b/src/ParseInstallation.js @@ -9,19 +9,19 @@ * @flow */ -import ParseObject from './ParseObject'; +import ParseObject from "./ParseObject"; -import type { AttributeMap } from './ObjectStateMutations'; +import type { AttributeMap } from "./ObjectStateMutations"; export default class Installation extends ParseObject { constructor(attributes: ?AttributeMap) { - super('_Installation'); - if (attributes && typeof attributes === 'object'){ + super("_Installation"); + 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"); } } } } -ParseObject.registerSubclass('_Installation', Installation); +ParseObject.registerSubclass("_Installation", Installation); diff --git a/src/ParseLiveQuery.js b/src/ParseLiveQuery.js index ee6a67624..0147fc4d1 100644 --- a/src/ParseLiveQuery.js +++ b/src/ParseLiveQuery.js @@ -9,9 +9,9 @@ * @flow */ -import EventEmitter from './EventEmitter'; -import LiveQueryClient from './LiveQueryClient'; -import CoreManager from './CoreManager'; +import EventEmitter from "./EventEmitter"; +import LiveQueryClient from "./LiveQueryClient"; +import CoreManager from "./CoreManager"; function getLiveQueryClient(): LiveQueryClient { return CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); @@ -68,7 +68,7 @@ LiveQuery.close = async () => { }; // Register a default onError callback to make sure we do not crash on error -LiveQuery.on('error', () => {}); +LiveQuery.on("error", () => {}); export default LiveQuery; @@ -85,29 +85,31 @@ const DefaultLiveQueryController = { } const [currentUser, installationId] = await Promise.all([ CoreManager.getUserController().currentUserAsync(), - CoreManager.getInstallationController().currentInstallationId() + CoreManager.getInstallationController().currentInstallationId(), ]); - const sessionToken = currentUser ? currentUser.getSessionToken() : undefined; + const sessionToken = currentUser + ? currentUser.getSessionToken() + : undefined; - let liveQueryServerURL = CoreManager.get('LIVEQUERY_SERVER_URL'); - if (liveQueryServerURL && liveQueryServerURL.indexOf('ws') !== 0) { + let liveQueryServerURL = CoreManager.get("LIVEQUERY_SERVER_URL"); + if (liveQueryServerURL && liveQueryServerURL.indexOf("ws") !== 0) { throw new Error( - 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' + "You need to set a proper Parse LiveQuery server url before using LiveQueryClient" ); } // If we can not find Parse.liveQueryServerURL, we try to extract it from Parse.serverURL if (!liveQueryServerURL) { - const serverURL = CoreManager.get('SERVER_URL'); - const protocol = serverURL.indexOf('https') === 0 ? 'wss://' : 'ws://'; - const host = serverURL.replace(/^https?:\/\//, ''); + const serverURL = CoreManager.get("SERVER_URL"); + const protocol = serverURL.indexOf("https") === 0 ? "wss://" : "ws://"; + const host = serverURL.replace(/^https?:\/\//, ""); liveQueryServerURL = protocol + host; - CoreManager.set('LIVEQUERY_SERVER_URL', liveQueryServerURL); + CoreManager.set("LIVEQUERY_SERVER_URL", liveQueryServerURL); } - const applicationId = CoreManager.get('APPLICATION_ID'); - const javascriptKey = CoreManager.get('JAVASCRIPT_KEY'); - const masterKey = CoreManager.get('MASTER_KEY'); + const applicationId = CoreManager.get("APPLICATION_ID"); + const javascriptKey = CoreManager.get("JAVASCRIPT_KEY"); + const masterKey = CoreManager.get("MASTER_KEY"); defaultLiveQueryClient = new LiveQueryClient({ applicationId, @@ -117,14 +119,14 @@ const DefaultLiveQueryController = { sessionToken, installationId, }); - defaultLiveQueryClient.on('error', (error) => { - LiveQuery.emit('error', error); + defaultLiveQueryClient.on("error", (error) => { + LiveQuery.emit("error", error); }); - defaultLiveQueryClient.on('open', () => { - LiveQuery.emit('open'); + defaultLiveQueryClient.on("open", () => { + LiveQuery.emit("open"); }); - defaultLiveQueryClient.on('close', () => { - LiveQuery.emit('close'); + defaultLiveQueryClient.on("close", () => { + LiveQuery.emit("close"); }); return defaultLiveQueryClient; }, diff --git a/src/ParseObject.js b/src/ParseObject.js index 989fa81e7..7725f4d68 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -9,17 +9,17 @@ * @flow */ -import CoreManager from './CoreManager'; -import canBeSerialized from './canBeSerialized'; -import decode from './decode'; -import encode from './encode'; -import escape from './escape'; -import ParseACL from './ParseACL'; -import parseDate from './parseDate'; -import ParseError from './ParseError'; -import ParseFile from './ParseFile'; -import { when, continueWhile, resolvingPromise } from './promiseUtils'; -import { DEFAULT_PIN, PIN_PREFIX } from './LocalDatastoreUtils'; +import CoreManager from "./CoreManager"; +import canBeSerialized from "./canBeSerialized"; +import decode from "./decode"; +import encode from "./encode"; +import escape from "./escape"; +import ParseACL from "./ParseACL"; +import parseDate from "./parseDate"; +import ParseError from "./ParseError"; +import ParseFile from "./ParseFile"; +import { when, continueWhile, resolvingPromise } from "./promiseUtils"; +import { DEFAULT_PIN, PIN_PREFIX } from "./LocalDatastoreUtils"; import { opFromJSON, @@ -30,36 +30,36 @@ import { AddOp, AddUniqueOp, RemoveOp, - RelationOp -} from './ParseOp'; -import ParseQuery from './ParseQuery'; -import ParseRelation from './ParseRelation'; -import * as SingleInstanceStateController from './SingleInstanceStateController'; -import unique from './unique'; -import * as UniqueInstanceStateController from './UniqueInstanceStateController'; -import unsavedChildren from './unsavedChildren'; + RelationOp, +} from "./ParseOp"; +import ParseQuery from "./ParseQuery"; +import ParseRelation from "./ParseRelation"; +import * as SingleInstanceStateController from "./SingleInstanceStateController"; +import unique from "./unique"; +import * as UniqueInstanceStateController from "./UniqueInstanceStateController"; +import unsavedChildren from "./unsavedChildren"; -import type { AttributeMap, OpsMap } from './ObjectStateMutations'; -import type { RequestOptions, FullOptions } from './RESTController'; +import type { AttributeMap, OpsMap } from "./ObjectStateMutations"; +import type { RequestOptions, FullOptions } from "./RESTController"; -const uuidv4 = require('uuid/v4'); +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 { @@ -78,12 +78,12 @@ if (singleInstance) { } function getServerUrlPath() { - let serverUrl = CoreManager.get('SERVER_URL'); - if (serverUrl[serverUrl.length - 1] !== '/') { - serverUrl += '/'; + let serverUrl = CoreManager.get("SERVER_URL"); + if (serverUrl[serverUrl.length - 1] !== "/") { + serverUrl += "/"; } - const url = serverUrl.replace(/https?:\/\//, ''); - return url.substr(url.indexOf('/')); + const url = serverUrl.replace(/https?:\/\//, ""); + return url.substr(url.indexOf("/")); } /** @@ -110,33 +110,37 @@ 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') { + if (typeof this.initialize === "function") { this.initialize.apply(this, arguments); } let toSet = null; this._objCount = objectCount++; - if (typeof className === 'string') { + if (typeof className === "string") { this.className = className; - if (attributes && typeof attributes === 'object') { + if (attributes && typeof attributes === "object") { toSet = attributes; } - } else if (className && typeof className === 'object') { + } else if (className && typeof className === "object") { this.className = className.className; toSet = {}; for (const attr in className) { - if (attr !== 'className') { + if (attr !== "className") { toSet[attr] = className[attr]; } } - if (attributes && typeof attributes === 'object') { + if (attributes && typeof attributes === "object") { options = attributes; } } 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"); } } @@ -154,7 +158,9 @@ class ParseObject { get attributes(): AttributeMap { const stateController = CoreManager.getObjectStateController(); - return Object.freeze(stateController.estimateAttributes(this._getStateIdentifier())); + return Object.freeze( + stateController.estimateAttributes(this._getStateIdentifier()) + ); } /** @@ -185,13 +191,13 @@ class ParseObject { * @returns {string} */ _getId(): string { - if (typeof this.id === 'string') { + if (typeof this.id === "string") { return this.id; } - if (typeof this._localId === 'string') { + if (typeof this._localId === "string") { return this._localId; } - const localId = 'local' + uuidv4(); + const localId = "local" + uuidv4(); this._localId = localId; return localId; } @@ -201,7 +207,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 +215,7 @@ class ParseObject { } return { id: id, - className: this.className + className: this.className, }; } else { return this; @@ -252,12 +258,15 @@ class ParseObject { _getDirtyObjectAttributes(): AttributeMap { const attributes = this.attributes; const stateController = CoreManager.getObjectStateController(); - const objectCache = stateController.getObjectCache(this._getStateIdentifier()); + const objectCache = stateController.getObjectCache( + this._getStateIdentifier() + ); const dirty = {}; for (const attr in attributes) { const val = attributes[attr]; - if (val && - typeof val === 'object' && + if ( + val && + typeof val === "object" && !(val instanceof ParseObject) && !(val instanceof ParseFile) && !(val instanceof ParseRelation) @@ -282,7 +291,7 @@ class ParseObject { _toFullJSON(seen?: Array, offline?: boolean): AttributeMap { const json: { [key: string]: mixed } = this.toJSON(seen, offline); - json.__type = 'Object'; + json.__type = "Object"; json.className = this.className; return json; } @@ -298,8 +307,8 @@ class ParseObject { for (let i = 0; i < pending.length; i += 1) { for (const field in pending[i]) { // Dot notation operations are handled later - if (field.includes('.')) { - const fieldName = field.split('.')[0]; + if (field.includes(".")) { + const fieldName = field.split(".")[0]; if (fieldName === attr) { isDotNotation = true; break; @@ -318,18 +327,18 @@ class ParseObject { } _getSaveParams(): SaveParams { - const method = this.id ? 'PUT' : 'POST'; + const method = this.id ? "PUT" : "POST"; const body = this._getSaveJSON(); - let path = 'classes/' + this.className; + let path = "classes/" + this.className; if (this.id) { - path += '/' + this.id; - } else if (this.className === '_User') { - path = 'users'; + path += "/" + this.id; + } else if (this.className === "_User") { + path = "users"; } return { method, body, - path + path, }; } @@ -341,19 +350,19 @@ class ParseObject { stateController.initializeState(this._getStateIdentifier()); const decoded = {}; for (const attr in serverData) { - if (attr === 'ACL') { + if (attr === "ACL") { decoded[attr] = new ParseACL(serverData[attr]); - } else if (attr !== 'objectId') { + } else if (attr !== "objectId") { decoded[attr] = decode(serverData[attr]); if (decoded[attr] instanceof ParseRelation) { decoded[attr]._ensureParentAndKey(this, attr); } } } - if (decoded.createdAt && typeof decoded.createdAt === 'string') { + if (decoded.createdAt && typeof decoded.createdAt === "string") { decoded.createdAt = parseDate(decoded.createdAt); } - if (decoded.updatedAt && typeof decoded.updatedAt === 'string') { + if (decoded.updatedAt && typeof decoded.updatedAt === "string") { decoded.updatedAt = parseDate(decoded.updatedAt); } if (!decoded.updatedAt && decoded.createdAt) { @@ -374,7 +383,9 @@ class ParseObject { if (this._localId && serverId) { if (singleInstance) { const stateController = CoreManager.getObjectStateController(); - const oldState = stateController.removeState(this._getStateIdentifier()); + const oldState = stateController.removeState( + this._getStateIdentifier() + ); this.id = serverId; delete this._localId; if (oldState) { @@ -395,18 +406,20 @@ class ParseObject { for (attr in pending) { if (pending[attr] instanceof RelationOp) { changes[attr] = pending[attr].applyTo(undefined, this, attr); - } else if (!(attr in response) && !attr.includes('.')) { + } else if (!(attr in response) && !attr.includes(".")) { // Only SetOps and UnsetOps should not come back with results changes[attr] = pending[attr].applyTo(undefined); } } 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') { + } else if (attr === "ACL") { changes[attr] = new ParseACL(response[attr]); - } else if (attr !== 'objectId') { + } else if (attr !== "objectId") { const val = decode(response[attr]); if (val && Object.getPrototypeOf(val) === Object.prototype) { changes[attr] = { ...this.attributes[attr], ...val }; @@ -450,12 +463,15 @@ class ParseObject { * @returns {object} */ toJSON(seen: Array | void, offline?: boolean): AttributeMap { - const seenEntry = this.id ? this.className + ':' + this.id : this; + const seenEntry = this.id ? this.className + ":" + this.id : this; seen = seen || [seenEntry]; const json = {}; const attrs = this.attributes; for (const attr in attrs) { - if ((attr === 'createdAt' || attr === 'updatedAt') && attrs[attr].toJSON) { + if ( + (attr === "createdAt" || attr === "updatedAt") && + attrs[attr].toJSON + ) { json[attr] = attrs[attr].toJSON(); } else { json[attr] = encode(attrs[attr], false, false, seen, offline); @@ -483,10 +499,10 @@ class ParseObject { return true; } return ( - (other instanceof ParseObject) && + other instanceof ParseObject && this.className === other.className && this.id === other.id && - typeof this.id !== 'undefined' + typeof this.id !== "undefined" ); } @@ -561,12 +577,12 @@ class ParseObject { */ toPointer(): Pointer { if (!this.id) { - throw new Error('Cannot create a pointer to an unsaved ParseObject'); + throw new Error("Cannot create a pointer to an unsaved ParseObject"); } return { - __type: 'Pointer', + __type: "Pointer", className: this.className, - objectId: this.id + objectId: this.id, }; } @@ -577,12 +593,12 @@ class ParseObject { */ toOfflinePointer(): Pointer { if (!this._localId) { - throw new Error('Cannot create a offline pointer to a saved ParseObject'); + throw new Error("Cannot create a offline pointer to a saved ParseObject"); } return { - __type: 'Object', + __type: "Object", className: this.className, - _localId: this._localId + _localId: this._localId, }; } @@ -606,7 +622,7 @@ class ParseObject { const value = this.get(attr); if (value) { if (!(value instanceof ParseRelation)) { - throw new Error('Called relation() on non-relation field ' + attr); + throw new Error("Called relation() on non-relation field " + attr); } value._ensureParentAndKey(this, attr); return value; @@ -623,11 +639,11 @@ class ParseObject { escape(attr: string): string { let val = this.attributes[attr]; if (val == null) { - return ''; + return ""; } - if (typeof val !== 'string') { - if (typeof val.toString !== 'function') { - return ''; + if (typeof val !== "string") { + if (typeof val.toString !== "function") { + return ""; } val = val.toString(); } @@ -682,10 +698,10 @@ class ParseObject { set(key: mixed, value: mixed, options?: mixed): ParseObject | boolean { let changes = {}; const newOps = {}; - if (key && typeof key === 'object') { + if (key && typeof key === "object") { changes = key; options = value; - } else if (typeof key === 'string') { + } else if (typeof key === "string") { changes[key] = value; } else { return this; @@ -693,34 +709,35 @@ class ParseObject { options = options || {}; let readonly = []; - if (typeof this.constructor.readOnlyAttributes === 'function') { + if (typeof this.constructor.readOnlyAttributes === "function") { readonly = readonly.concat(this.constructor.readOnlyAttributes()); } for (const k in changes) { - if (k === 'createdAt' || k === 'updatedAt') { + if (k === "createdAt" || k === "updatedAt") { // This property is read-only, but for legacy reasons we silently // ignore it continue; } if (readonly.indexOf(k) > -1) { - throw new Error('Cannot modify readonly attribute: ' + k); + throw new Error("Cannot modify readonly attribute: " + k); } if (options.unset) { newOps[k] = new UnsetOp(); } else if (changes[k] instanceof Op) { newOps[k] = changes[k]; - } else if (changes[k] && - typeof changes[k] === 'object' && - typeof changes[k].__op === 'string' + } else if ( + changes[k] && + typeof changes[k] === "object" && + typeof changes[k].__op === "string" ) { newOps[k] = opFromJSON(changes[k]); - } else if (k === 'objectId' || k === 'id') { - if (typeof changes[k] === 'string') { + } else if (k === "objectId" || k === "id") { + if (typeof changes[k] === "string") { this.id = changes[k]; } } else if ( - k === 'ACL' && - typeof changes[k] === 'object' && + k === "ACL" && + typeof changes[k] === "object" && !(changes[k] instanceof ParseACL) ) { newOps[k] = new SetOp(new ParseACL(changes[k])); @@ -737,8 +754,8 @@ class ParseObject { // Only set nested fields if exists const serverData = this._getServerData(); - if (typeof key === 'string' && key.includes('.')) { - const field = key.split('.')[0]; + if (typeof key === "string" && key.includes(".")) { + const field = key.split(".")[0]; if (!serverData[field]) { return this; } @@ -748,7 +765,11 @@ class ParseObject { const newValues = {}; for (const attr in newOps) { if (newOps[attr] instanceof RelationOp) { - newValues[attr] = newOps[attr].applyTo(currentAttributes[attr], this, attr); + newValues[attr] = newOps[attr].applyTo( + currentAttributes[attr], + this, + attr + ); } else if (!(newOps[attr] instanceof UnsetOp)) { newValues[attr] = newOps[attr].applyTo(currentAttributes[attr]); } @@ -758,7 +779,7 @@ class ParseObject { if (!options.ignoreValidation) { const validation = this.validate(newValues); if (validation) { - if (typeof options.error === 'function') { + if (typeof options.error === "function") { options.error(this, validation); } return false; @@ -785,7 +806,10 @@ class ParseObject { * @param options * @returns {(ParseObject | boolean)} */ - unset(attr: string, options?: { [opt: string]: mixed }): ParseObject | boolean { + unset( + attr: string, + options?: { [opt: string]: mixed } + ): ParseObject | boolean { options = options || {}; options.unset = true; return this.set(attr, null, options); @@ -800,11 +824,11 @@ class ParseObject { * @returns {(ParseObject|boolean)} */ increment(attr: string, amount?: number): ParseObject | boolean { - if (typeof amount === 'undefined') { + if (typeof amount === "undefined") { amount = 1; } - if (typeof amount !== 'number') { - throw new Error('Cannot increment by a non-numeric amount.'); + if (typeof amount !== "number") { + throw new Error("Cannot increment by a non-numeric amount."); } return this.set(attr, new IncrementOp(amount)); } @@ -818,11 +842,11 @@ class ParseObject { * @returns {(ParseObject | boolean)} */ decrement(attr: string, amount?: number): ParseObject | boolean { - if (typeof amount === 'undefined') { + if (typeof amount === "undefined") { amount = 1; } - if (typeof amount !== 'number') { - throw new Error('Cannot decrement by a non-numeric amount.'); + if (typeof amount !== "number") { + throw new Error("Cannot decrement by a non-numeric amount."); } return this.set(attr, new IncrementOp(amount * -1)); } @@ -930,7 +954,7 @@ class ParseObject { clone.className = this.className; } let attributes = this.attributes; - if (typeof this.constructor.readOnlyAttributes === 'function') { + if (typeof this.constructor.readOnlyAttributes === "function") { const readonly = this.constructor.readOnlyAttributes() || []; // Attributes are frozen, so we have to rebuild an object, // rather than delete readonly keys @@ -966,7 +990,10 @@ class ParseObject { const stateController = CoreManager.getObjectStateController(); if (stateController) { - stateController.duplicateState(this._getStateIdentifier(), clone._getStateIdentifier()); + stateController.duplicateState( + this._getStateIdentifier(), + clone._getStateIdentifier() + ); } return clone; } @@ -1016,7 +1043,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) { @@ -1047,14 +1074,11 @@ class ParseObject { * @see Parse.Object#set */ 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.' - ); + if (attrs.hasOwnProperty("ACL") && !(attrs.ACL instanceof ParseACL)) { + 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); } } @@ -1068,7 +1092,7 @@ class ParseObject { * @see Parse.Object#get */ getACL(): ?ParseACL { - const acl = this.get('ACL'); + const acl = this.get("ACL"); if (acl instanceof ParseACL) { return acl; } @@ -1084,7 +1108,7 @@ class ParseObject { * @see Parse.Object#set */ setACL(acl: ParseACL, options?: mixed): ParseObject | boolean { - return this.set('ACL', acl, options); + return this.set("ACL", acl, options); } /** @@ -1094,13 +1118,15 @@ 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." + ); } } } @@ -1115,8 +1141,8 @@ class ParseObject { clear(): ParseObject | boolean { const attributes = this.attributes; const erasable = {}; - let readonly = ['createdAt', 'updatedAt']; - if (typeof this.constructor.readOnlyAttributes === 'function') { + let readonly = ["createdAt", "updatedAt"]; + if (typeof this.constructor.readOnlyAttributes === "function") { readonly = readonly.concat(this.constructor.readOnlyAttributes()); } for (const attr in attributes) { @@ -1147,16 +1173,19 @@ class ParseObject { fetch(options: RequestOptions): Promise { options = options || {}; const fetchOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { fetchOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { fetchOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { fetchOptions.context = options.context; } - if (options.hasOwnProperty('include')) { + if (options.hasOwnProperty("include")) { fetchOptions.include = []; if (Array.isArray(options.include)) { options.include.forEach((key) => { @@ -1192,7 +1221,10 @@ 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); @@ -1263,9 +1295,9 @@ class ParseObject { ): Promise { let attrs; let options; - if (typeof arg1 === 'object' || typeof arg1 === 'undefined') { + if (typeof arg1 === "object" || typeof arg1 === "undefined") { attrs = arg1; - if (typeof arg2 === 'object') { + if (typeof arg2 === "object") { options = arg2; } } else { @@ -1284,20 +1316,30 @@ class ParseObject { options = options || {}; const saveOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { saveOptions.useMasterKey = !!options.useMasterKey; } - if (options.hasOwnProperty('sessionToken') && typeof options.sessionToken === 'string') { + if ( + options.hasOwnProperty("sessionToken") && + typeof options.sessionToken === "string" + ) { saveOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('installationId') && typeof options.installationId === 'string') { + if ( + options.hasOwnProperty("installationId") && + typeof options.installationId === "string" + ) { saveOptions.installationId = options.installationId; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { saveOptions.context = options.context; } const controller = CoreManager.getObjectController(); - const unsaved = options.cascadeSave !== false ? unsavedChildren(this) : null; + const unsaved = + options.cascadeSave !== false ? unsavedChildren(this) : null; return controller.save(unsaved, saveOptions).then(() => { return controller.save(this, saveOptions); }); @@ -1320,22 +1362,22 @@ class ParseObject { destroy(options: RequestOptions): Promise { options = options || {}; const destroyOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { destroyOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { destroyOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { destroyOptions.context = options.context; } if (!this.id) { return Promise.resolve(); } - return CoreManager.getObjectController().destroy( - this, - destroyOptions - ); + return CoreManager.getObjectController().destroy(this, destroyOptions); } /** @@ -1384,7 +1426,9 @@ class ParseObject { async isPinned(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } const objectKey = localDatastore.getKeyForObject(this); const pin = await localDatastore.fromPinWithName(objectKey); @@ -1440,12 +1484,12 @@ class ParseObject { async fetchFromLocalDatastore(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - throw new Error('Parse.enableLocalDatastore() must be called first'); + throw new Error("Parse.enableLocalDatastore() must be called first"); } const objectKey = localDatastore.getKeyForObject(this); const pinned = await localDatastore._serializeObject(objectKey); if (!pinned) { - throw new Error('Cannot fetch an unsaved ParseObject'); + throw new Error("Cannot fetch an unsaved ParseObject"); } const result = ParseObject.fromJSON(pinned); this._finishFetch(result.toJSON()); @@ -1488,20 +1532,16 @@ class ParseObject { */ static fetchAll(list: Array, options: RequestOptions = {}) { const queryOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { queryOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { queryOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('include')) { + 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 +1573,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 +1613,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); @@ -1597,20 +1645,16 @@ class ParseObject { options = options || {}; const queryOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { queryOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { queryOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('include')) { + 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) { @@ -1677,22 +1721,25 @@ class ParseObject { */ static destroyAll(list: Array, options = {}) { const destroyOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { destroyOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { destroyOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { + if ( + options.hasOwnProperty("batchSize") && + typeof options.batchSize === "number" + ) { destroyOptions.batchSize = options.batchSize; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { destroyOptions.context = options.context; } - return CoreManager.getObjectController().destroy( - list, - destroyOptions - ); + return CoreManager.getObjectController().destroy(list, destroyOptions); } /** @@ -1715,22 +1762,25 @@ class ParseObject { */ static saveAll(list: Array, options: RequestOptions = {}) { const saveOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { saveOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { saveOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { + if ( + options.hasOwnProperty("batchSize") && + typeof options.batchSize === "number" + ) { saveOptions.batchSize = options.batchSize; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { saveOptions.context = options.context; } - return CoreManager.getObjectController().save( - list, - saveOptions - ); + return CoreManager.getObjectController().save(list, saveOptions); } /** @@ -1764,13 +1814,13 @@ class ParseObject { */ static fromJSON(json: any, override?: boolean) { if (!json.className) { - throw new Error('Cannot create an object without a className'); + throw new Error("Cannot create an object without a className"); } const constructor = classMap[json.className]; const o = constructor ? new constructor() : new ParseObject(json.className); const otherAttributes = {}; for (const attr in json) { - if (attr !== 'className' && attr !== '__type') { + if (attr !== "className" && attr !== "__type") { otherAttributes[attr] = json[attr]; } } @@ -1780,7 +1830,7 @@ class ParseObject { o.id = otherAttributes.objectId; } let preserved = null; - if (typeof o._preserveFieldsOnFetch === 'function') { + if (typeof o._preserveFieldsOnFetch === "function") { preserved = o._preserveFieldsOnFetch(); } o._clearServerData(); @@ -1805,16 +1855,16 @@ class ParseObject { * @param {Function} constructor The subclass */ static registerSubclass(className: string, constructor: any) { - if (typeof className !== 'string') { - throw new TypeError('The first argument must be a valid class name.'); + if (typeof className !== "string") { + throw new TypeError("The first argument must be a valid class name."); } - if (typeof constructor === 'undefined') { - throw new TypeError('You must supply a subclass constructor.'); + if (typeof constructor === "undefined") { + throw new TypeError("You must supply a subclass constructor."); } - if (typeof constructor !== 'function') { + if (typeof constructor !== "function") { throw new TypeError( - 'You must register the subclass constructor. ' + - 'Did you attempt to register an instance of the subclass?' + "You must register the subclass constructor. " + + "Did you attempt to register an instance of the subclass?" ); } classMap[className] = constructor; @@ -1861,38 +1911,41 @@ class ParseObject { * @returns {Parse.Object} A new subclass of Parse.Object. */ static extend(className: any, protoProps: any, classProps: any) { - if (typeof className !== 'string') { - if (className && typeof className.className === 'string') { + if (typeof className !== "string") { + 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.' + "Parse.Object.extend's first argument should be the className." ); } } let adjustedClassName = className; - if (adjustedClassName === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { - adjustedClassName = '_User'; + if ( + adjustedClassName === "User" && + CoreManager.get("PERFORM_USER_REWRITE") + ) { + adjustedClassName = "_User"; } let parentProto = ParseObject.prototype; - if (this.hasOwnProperty('__super__') && this.__super__) { + if (this.hasOwnProperty("__super__") && this.__super__) { parentProto = this.prototype; } 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 - if (typeof this.initialize === 'function') { + if (typeof this.initialize === "function") { 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,18 +1957,18 @@ class ParseObject { value: ParseObjectSubclass, enumerable: false, writable: true, - configurable: true - } + configurable: true, + }, }); if (protoProps) { for (const prop in protoProps) { - if (prop !== 'className') { + if (prop !== "className") { Object.defineProperty(ParseObjectSubclass.prototype, prop, { value: protoProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -1923,23 +1976,33 @@ class ParseObject { if (classProps) { for (const prop in classProps) { - if (prop !== 'className') { + if (prop !== "className") { Object.defineProperty(ParseObjectSubclass, prop, { value: classProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } } - ParseObjectSubclass.extend = function(name, protoProps, classProps) { - if (typeof name === 'string') { - return ParseObject.extend.call(ParseObjectSubclass, 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); - } + return ParseObject.extend.call( + ParseObjectSubclass, + adjustedClassName, + name, + protoProps + ); + }; ParseObjectSubclass.createWithoutData = ParseObject.createWithoutData; classMap[adjustedClassName] = ParseObjectSubclass; @@ -1993,7 +2056,9 @@ class ParseObject { static pinAll(objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return ParseObject.pinAllWithName(DEFAULT_PIN, objects); } @@ -2016,10 +2081,15 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the pin completes. * @static */ - static pinAllWithName(name: string, objects: Array): Promise { + static pinAllWithName( + name: string, + objects: Array + ): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return localDatastore._handlePinAllWithName(name, objects); } @@ -2039,7 +2109,9 @@ class ParseObject { static unPinAll(objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return ParseObject.unPinAllWithName(DEFAULT_PIN, objects); } @@ -2056,10 +2128,15 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the unPin completes. * @static */ - static unPinAllWithName(name: string, objects: Array): Promise { + static unPinAllWithName( + name: string, + objects: Array + ): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return localDatastore._handleUnPinAllWithName(name, objects); } @@ -2077,7 +2154,9 @@ class ParseObject { static unPinAllObjects(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return localDatastore.unPinWithName(DEFAULT_PIN); } @@ -2097,14 +2176,20 @@ class ParseObject { static unPinAllObjectsWithName(name: string): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject('Parse.enableLocalDatastore() must be called first'); + return Promise.reject( + "Parse.enableLocalDatastore() must be called first" + ); } return localDatastore.unPinWithName(PIN_PREFIX + name); } } 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) { @@ -2125,13 +2210,13 @@ const DefaultController = { if (className !== el.className) { error = new ParseError( ParseError.INVALID_CLASS_NAME, - 'All objects should be of the same class' + "All objects should be of the same class" ); } if (!el.id) { error = new ParseError( ParseError.MISSING_OBJECT_ID, - 'All objects must have an ID' + "All objects must have an ID" ); } if (forceFetch || !el.isDataAvailable()) { @@ -2144,7 +2229,7 @@ const DefaultController = { return Promise.reject(error); } const query = new ParseQuery(className); - query.containedIn('objectId', ids); + query.containedIn("objectId", ids); if (options && options.include) { query.include(options.include); } @@ -2161,7 +2246,7 @@ const DefaultController = { return Promise.reject( new ParseError( ParseError.OBJECT_NOT_FOUND, - 'All objects must exist on the server.' + "All objects must exist on the server." ) ); } @@ -2185,10 +2270,12 @@ 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 = {}; @@ -2196,8 +2283,8 @@ const DefaultController = { params.include = options.include.join(); } return RESTController.request( - 'GET', - 'classes/' + target.className + '/' + target._getId(), + "GET", + "classes/" + target.className + "/" + target._getId(), params, options ).then(async (response) => { @@ -2211,8 +2298,14 @@ 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(); @@ -2238,17 +2331,27 @@ const DefaultController = { const errors = []; 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')) { + if (results[i] && results[i].hasOwnProperty("error")) { const err = new ParseError( results[i].error.code, results[i].error.error @@ -2273,8 +2376,8 @@ const DefaultController = { }); } else if (target instanceof ParseObject) { return RESTController.request( - 'DELETE', - 'classes/' + target.className + '/' + target._getId(), + "DELETE", + "classes/" + target.className + "/" + target._getId(), {}, options ).then(async () => { @@ -2285,8 +2388,14 @@ const DefaultController = { return Promise.resolve(target); }, - save(target: ParseObject | Array, options: RequestOptions) { - const batchSize = (options && options.batchSize) ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); + save( + target: ParseObject | Array, + options: RequestOptions + ) { + const batchSize = + options && options.batchSize + ? options.batchSize + : CoreManager.get("REQUEST_BATCH_SIZE"); const localDatastore = CoreManager.getLocalDatastore(); const mapIdForPin = {}; @@ -2320,121 +2429,151 @@ 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); } for (const object of target) { - await localDatastore._updateLocalIdForObject(mapIdForPin[object.id], object); + await localDatastore._updateLocalIdForObject( + mapIdForPin[object.id], + object + ); await localDatastore._updateObjectIfPinned(object); } 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); - }); - } + ).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..f5973e0c0 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -9,49 +9,49 @@ * @flow */ -import arrayContainsObject from './arrayContainsObject'; -import decode from './decode'; -import encode from './encode'; -import ParseObject from './ParseObject'; -import ParseRelation from './ParseRelation'; -import unique from './unique'; +import arrayContainsObject from "./arrayContainsObject"; +import decode from "./decode"; +import encode from "./encode"; +import ParseObject from "./ParseObject"; +import ParseRelation from "./ParseRelation"; +import unique from "./unique"; export function opFromJSON(json: { [key: string]: any }): ?Op { if (!json || !json.__op) { return null; } switch (json.__op) { - case 'Delete': + case "Delete": return new UnsetOp(); - case 'Increment': + case "Increment": return new IncrementOp(json.amount); - case 'Add': + case "Add": return new AddOp(decode(json.objects)); - case 'AddUnique': + case "AddUnique": return new AddUniqueOp(decode(json.objects)); - case 'Remove': + case "Remove": return new RemoveOp(decode(json.objects)); - case 'AddRelation': { + case "AddRelation": { const toAdd = decode(json.objects); if (!Array.isArray(toAdd)) { return new RelationOp([], []); } return new RelationOp(toAdd, []); } - case 'RemoveRelation': { + case "RemoveRelation": { const toRemove = decode(json.objects); if (!Array.isArray(toRemove)) { return new RelationOp([], []); } return new RelationOp([], toRemove); } - case 'Batch': { + case "Batch": { let toAdd = []; let toRemove = []; for (let i = 0; i < json.ops.length; i++) { - if (json.ops[i].__op === 'AddRelation') { + if (json.ops[i].__op === "AddRelation") { toAdd = toAdd.concat(decode(json.ops[i].objects)); - } else if (json.ops[i].__op === 'RemoveRelation') { + } else if (json.ops[i].__op === "RemoveRelation") { toRemove = toRemove.concat(decode(json.ops[i].objects)); } } @@ -99,7 +99,7 @@ export class UnsetOp extends Op { } toJSON(): { __op: string } { - return { __op: 'Delete' }; + return { __op: "Delete" }; } } @@ -108,20 +108,20 @@ export class IncrementOp extends Op { constructor(amount: number) { super(); - if (typeof amount !== 'number') { + if (typeof amount !== "number") { throw new TypeError( - 'Increment Op must be initialized with a numeric amount.' + "Increment Op must be initialized with a numeric amount." ); } this._amount = amount; } applyTo(value: ?mixed): number { - if (typeof value === 'undefined') { + if (typeof value === "undefined") { return this._amount; } - if (typeof value !== 'number') { - throw new TypeError('Cannot increment a non-numeric value.'); + if (typeof value !== "number") { + throw new TypeError("Cannot increment a non-numeric value."); } return this._amount + value; } @@ -139,11 +139,11 @@ export class IncrementOp extends Op { if (previous instanceof IncrementOp) { return new IncrementOp(this.applyTo(previous._amount)); } - throw new Error('Cannot merge Increment Op with the previous Op'); + throw new Error("Cannot merge Increment Op with the previous Op"); } - toJSON(): { __op: string; amount: number } { - return { __op: 'Increment', amount: this._amount }; + toJSON(): { __op: string, amount: number } { + return { __op: "Increment", amount: this._amount }; } } @@ -152,7 +152,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 { @@ -162,7 +162,7 @@ export class AddOp extends Op { if (Array.isArray(value)) { return value.concat(this._value); } - throw new Error('Cannot add elements to a non-array value'); + throw new Error("Cannot add elements to a non-array value"); } mergeWith(previous: Op): Op { @@ -178,11 +178,11 @@ export class AddOp extends Op { if (previous instanceof AddOp) { return new AddOp(this.applyTo(previous._value)); } - throw new Error('Cannot merge Add Op with the previous Op'); + throw new Error("Cannot merge Add Op with the previous Op"); } - toJSON(): { __op: string; objects: mixed } { - return { __op: 'Add', objects: encode(this._value, false, true) }; + toJSON(): { __op: string, objects: mixed } { + return { __op: "Add", objects: encode(this._value, false, true) }; } } @@ -210,10 +210,10 @@ export class AddUniqueOp extends Op { toAdd.push(v); } } - }) + }); return value.concat(toAdd); } - throw new Error('Cannot add elements to a non-array value'); + throw new Error("Cannot add elements to a non-array value"); } mergeWith(previous: Op): Op { @@ -229,11 +229,11 @@ export class AddUniqueOp extends Op { if (previous instanceof AddUniqueOp) { return new AddUniqueOp(this.applyTo(previous._value)); } - throw new Error('Cannot merge AddUnique Op with the previous Op'); + throw new Error("Cannot merge AddUnique Op with the previous Op"); } - toJSON(): { __op: string; objects: mixed } { - return { __op: 'AddUnique', objects: encode(this._value, false, true) }; + toJSON(): { __op: string, objects: mixed } { + return { __op: "AddUnique", objects: encode(this._value, false, true) }; } } @@ -260,7 +260,8 @@ 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 && + if ( + removed[j] instanceof ParseObject && this._value[i].id === removed[j].id ) { removed.splice(j, 1); @@ -271,7 +272,7 @@ export class RemoveOp extends Op { } return removed; } - throw new Error('Cannot remove elements from a non-array value'); + throw new Error("Cannot remove elements from a non-array value"); } mergeWith(previous: Op): Op { @@ -299,11 +300,11 @@ export class RemoveOp extends Op { } return new RemoveOp(uniques); } - throw new Error('Cannot merge Remove Op with the previous Op'); + throw new Error("Cannot merge Remove Op with the previous Op"); } - toJSON(): { __op: string; objects: mixed } { - return { __op: 'Remove', objects: encode(this._value, false, true) }; + toJSON(): { __op: string, objects: mixed } { + return { __op: "Remove", objects: encode(this._value, false, true) }; } } @@ -329,12 +330,12 @@ export class RelationOp extends Op { } _extractId(obj: string | ParseObject): string { - if (typeof obj === 'string') { + if (typeof obj === "string") { return obj; } if (!obj.id) { throw new Error( - 'You cannot add or remove an unsaved Parse Object from a relation' + "You cannot add or remove an unsaved Parse Object from a relation" ); } if (!this._targetClassName) { @@ -342,20 +343,29 @@ 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 + '.' + "Tried to create a Relation with 2 different object types: " + + this._targetClassName + + " and " + + obj.className + + "." ); } return obj.id; } - applyTo(value: mixed, object?: { className: string, id: ?string }, key?: string): ?ParseRelation { + 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) { + if (object.id && object.id.indexOf("local") === 0) { parent._localId = object.id; } else if (object.id) { parent.id = object.id; @@ -369,8 +379,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 +392,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"); } } @@ -389,15 +400,23 @@ export class RelationOp extends Op { if (!previous) { return this; } else if (previous instanceof UnsetOp) { - throw new Error('You cannot modify a relation after deleting it.'); - } else if (previous instanceof SetOp && previous._value instanceof ParseRelation) { + throw new Error("You cannot modify a relation after deleting it."); + } 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([]); @@ -432,15 +451,15 @@ export class RelationOp extends Op { newRelation._targetClassName = this._targetClassName; return newRelation; } - throw new Error('Cannot merge Relation Op with the previous Op'); + throw new Error("Cannot merge Relation Op with the previous Op"); } - toJSON(): { __op?: string; objects?: mixed; ops?: mixed } { + toJSON(): { __op?: string, objects?: mixed, ops?: mixed } { const idToPointer = (id) => { return { - __type: 'Pointer', + __type: "Pointer", className: this._targetClassName, - objectId: id + objectId: id, }; }; @@ -450,15 +469,15 @@ export class RelationOp extends Op { if (this.relationsToAdd.length > 0) { pointers = this.relationsToAdd.map(idToPointer); - adds = { __op: 'AddRelation', objects: pointers }; + adds = { __op: "AddRelation", objects: pointers }; } if (this.relationsToRemove.length > 0) { pointers = this.relationsToRemove.map(idToPointer); - removes = { __op: 'RemoveRelation', objects: pointers }; + removes = { __op: "RemoveRelation", objects: pointers }; } if (adds && removes) { - return { __op: 'Batch', ops: [adds, removes] }; + return { __op: "Batch", ops: [adds, removes] }; } return adds || removes || {}; diff --git a/src/ParsePolygon.js b/src/ParsePolygon.js index 265900704..001db1250 100644 --- a/src/ParsePolygon.js +++ b/src/ParsePolygon.js @@ -9,7 +9,7 @@ * @flow */ -import ParseGeoPoint from './ParseGeoPoint'; +import ParseGeoPoint from "./ParseGeoPoint"; /** * Creates a new Polygon with any of the following forms:
@@ -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,10 +60,10 @@ class ParsePolygon { * * @returns {object} */ - toJSON(): { __type: string; coordinates: Array>;} { + toJSON(): { __type: string, coordinates: Array> } { ParsePolygon._validate(this._coordinates); return { - __type: 'Polygon', + __type: "Polygon", coordinates: this._coordinates, }; } @@ -77,14 +75,19 @@ 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 +114,31 @@ 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; @@ -140,12 +154,14 @@ class ParsePolygon { * @throws {TypeError} * @returns {number[][]} Array of coordinates if validated. */ - static _validate(coords: Array> | Array): Array> { + static _validate( + coords: Array> | Array + ): Array> { if (!Array.isArray(coords)) { - throw new TypeError('Coordinates must be an Array'); + throw new TypeError("Coordinates must be an Array"); } if (coords.length < 3) { - throw new TypeError('Polygon must have at least 3 GeoPoints or Points'); + throw new TypeError("Polygon must have at least 3 GeoPoints or Points"); } const points = []; for (let i = 0; i < coords.length; i += 1) { @@ -156,7 +172,9 @@ class ParsePolygon { } else if (Array.isArray(coord) && coord.length === 2) { geoPoint = new ParseGeoPoint(coord[0], coord[1]); } else { - throw new TypeError('Coordinates must be an Array of GeoPoints or Points'); + throw new TypeError( + "Coordinates must be an Array of GeoPoints or Points" + ); } points.push([geoPoint.latitude, geoPoint.longitude]); } diff --git a/src/ParseQuery.js b/src/ParseQuery.js index 93712a57b..dca6bb38a 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -9,39 +9,39 @@ * @flow */ -import CoreManager from './CoreManager'; -import encode from './encode'; -import { continueWhile } from './promiseUtils'; -import ParseError from './ParseError'; -import ParseGeoPoint from './ParseGeoPoint'; -import ParseObject from './ParseObject'; -import OfflineQuery from './OfflineQuery'; -import { DEFAULT_PIN } from './LocalDatastoreUtils'; - -import type LiveQuerySubscription from './LiveQuerySubscription'; -import type { RequestOptions, FullOptions } from './RESTController'; +import CoreManager from "./CoreManager"; +import encode from "./encode"; +import { continueWhile } from "./promiseUtils"; +import ParseError from "./ParseError"; +import ParseGeoPoint from "./ParseGeoPoint"; +import ParseObject from "./ParseObject"; +import OfflineQuery from "./OfflineQuery"; +import { DEFAULT_PIN } from "./LocalDatastoreUtils"; + +import type LiveQuerySubscription from "./LiveQuerySubscription"; +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, }; /** @@ -54,7 +54,7 @@ export type QueryJSON = { * @returns {string} */ function quote(s: string): string { - return '\\Q' + s.replace('\\E', '\\E\\\\E\\Q') + '\\E'; + return "\\Q" + s.replace("\\E", "\\E\\\\E\\Q") + "\\E"; } /** @@ -73,7 +73,7 @@ function _getClassNameFromQueries(queries: Array): ?string { } if (className !== q.className) { - throw new Error('All queries must be for the same class.'); + throw new Error("All queries must be for the same class."); } }); return className; @@ -84,14 +84,14 @@ 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)){ + 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 @@ -104,7 +104,7 @@ function handleSelectResult(data: any, select: Array){ if (obj && !obj.hasOwnProperty(component)) { obj[component] = undefined; } - if (obj && typeof obj === 'object') { + if (obj && typeof obj === "object") { obj = obj[component]; } @@ -125,23 +125,31 @@ 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]; } } } for (const key in mask) { - if (dest[key] !== undefined && dest[key] !== null && src !== undefined && src !== null) { + if ( + dest[key] !== undefined && + dest[key] !== null && + src !== undefined && + src !== null + ) { //traverse into objects as needed copyMissingDataWithMask(src[key], dest[key], mask[key], true); } @@ -151,17 +159,17 @@ function copyMissingDataWithMask(src, dest, mask, copyThisLevel){ function handleOfflineSort(a, b, sorts) { let order = sorts[0]; const operator = order.slice(0, 1); - const isDescending = operator === '-'; + const isDescending = operator === "-"; if (isDescending) { order = order.substring(1); } - if (order === '_created_at') { - order = 'createdAt'; + if (order === "_created_at") { + order = "createdAt"; } - if (order === '_updated_at') { - order = 'updatedAt'; + 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); @@ -249,16 +257,16 @@ class ParseQuery { * @param {(string | Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string. */ constructor(objectClass: string | ParseObject) { - if (typeof objectClass === 'string') { - if (objectClass === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { - this.className = '_User'; + if (typeof objectClass === "string") { + if (objectClass === "User" && CoreManager.get("PERFORM_USER_REWRITE")) { + this.className = "_User"; } else { this.className = objectClass; } } else if (objectClass instanceof ParseObject) { this.className = objectClass.className; - } else if (typeof objectClass === 'function') { - if (typeof objectClass.className === 'string') { + } else if (typeof objectClass === "function") { + if (typeof objectClass.className === "string") { this.className = objectClass.className; } else { const obj = new objectClass(); @@ -266,7 +274,7 @@ class ParseQuery { } } else { throw new TypeError( - 'A ParseQuery must be constructed with a ParseObject or class name.' + "A ParseQuery must be constructed with a ParseObject or class name." ); } @@ -285,7 +293,7 @@ class ParseQuery { this._xhrRequest = { task: null, onchange: () => {}, - } + }; } /** @@ -342,7 +350,7 @@ class ParseQuery { * @returns {Parse.Query} */ _addCondition(key: string, condition: string, value: mixed): ParseQuery { - if (!this._where[key] || typeof this._where[key] === 'string') { + if (!this._where[key] || typeof this._where[key] === "string") { this._where[key] = {}; } this._where[key][condition] = encode(value, false, true); @@ -356,26 +364,36 @@ class ParseQuery { * @returns {string} */ _regexStartWith(string: string): string { - return '^' + quote(string); + return "^" + quote(string); } async _handleOfflineQuery(params: any) { 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); + 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); if (params.keys) { - let keys = params.keys.split(','); - const alwaysSelectedKeys = ['className', 'objectId', 'createdAt', 'updatedAt', 'ACL']; + let keys = params.keys.split(","); + const alwaysSelectedKeys = [ + "className", + "objectId", + "createdAt", + "updatedAt", + "ACL", + ]; keys = keys.concat(alwaysSelectedKeys); results = results.map((object) => { const json = object._toFullJSON(); @@ -388,14 +406,14 @@ class ParseQuery { }); } if (params.order) { - const sorts = params.order.split(','); + const sorts = params.order.split(","); results.sort((a, b) => { return handleOfflineSort(a, b, sorts); }); } - 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 +431,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,17 +445,17 @@ class ParseQuery { */ toJSON(): QueryJSON { const params: QueryJSON = { - where: this._where + where: this._where, }; if (this._include.length) { - params.include = this._include.join(','); + params.include = this._include.join(","); } if (this._exclude.length) { - params.excludeKeys = this._exclude.join(','); + params.excludeKeys = this._exclude.join(","); } if (this._select) { - params.keys = this._select.join(','); + params.keys = this._select.join(","); } if (this._count) { params.count = 1; @@ -449,7 +467,7 @@ class ParseQuery { params.skip = this._skip; } if (this._order) { - params.order = this._order.join(','); + params.order = this._order.join(","); } if (this._readPreference) { params.readPreference = this._readPreference; @@ -495,7 +513,6 @@ 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; } @@ -517,7 +534,7 @@ class ParseQuery { } if (json.limit) { - this._limit = json.limit; + this._limit = json.limit; } if (json.skip) { @@ -549,15 +566,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; - } /** @@ -591,16 +622,20 @@ class ParseQuery { * the query completes. */ get(objectId: string, options?: FullOptions): Promise { - this.equalTo('objectId', objectId); + this.equalTo("objectId", objectId); const firstOptions = {}; - if (options && options.hasOwnProperty('useMasterKey')) { + if (options && options.hasOwnProperty("useMasterKey")) { firstOptions.useMasterKey = options.useMasterKey; } - if (options && options.hasOwnProperty('sessionToken')) { + if (options && options.hasOwnProperty("sessionToken")) { firstOptions.sessionToken = options.sessionToken; } - if (options && options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options && + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { firstOptions.context = options.context; } @@ -611,7 +646,7 @@ class ParseQuery { const errorObject = new ParseError( ParseError.OBJECT_NOT_FOUND, - 'Object not found.' + "Object not found." ); return Promise.reject(errorObject); }); @@ -636,13 +671,16 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { findOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { findOptions.context = options.context; } this._setRequestTask(findOptions); @@ -654,41 +692,39 @@ class ParseQuery { if (this._queriesLocalDatastore) { return this._handleOfflineQuery(this.toJSON()); } - 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) => { - // In cases of relations, the server may send back a className - // on the top level of the payload - const override = response.className || this.className; - if (!data.className) { - data.className = override; + 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) => { + // In cases of relations, the server may send back a className + // on the top level of the payload + const override = response.className || this.className; + if (!data.className) { + data.className = override; + } - // Make sure the data object contains keys for all objects that - // have been requested with a select, so that our cached state - // updates correctly. - if (select) { - handleSelectResult(data, select); - } + // Make sure the data object contains keys for all objects that + // have been requested with a select, so that our cached state + // updates correctly. + if (select) { + handleSelectResult(data, select); + } - return ParseObject.fromJSON(data, !select); - }); + return ParseObject.fromJSON(data, !select); + }); - const count = response.count; + const count = response.count; - if(typeof count === "number"){ - return {results, count}; - } else { - return results; - } - }); + if (typeof count === "number") { + return { results, count }; + } else { + return results; + } + }); } /** @@ -731,10 +767,10 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { findOptions.sessionToken = options.sessionToken; } this._setRequestTask(findOptions); @@ -745,13 +781,11 @@ class ParseQuery { params.limit = 0; params.count = 1; - return controller.find( - this.className, - params, - findOptions - ).then((result) => { - return result.count; - }); + return controller + .find(this.className, params, findOptions) + .then((result) => { + return result.count; + }); } /** @@ -772,7 +806,7 @@ class ParseQuery { const distinctOptions = {}; distinctOptions.useMasterKey = true; - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { distinctOptions.sessionToken = options.sessionToken; } this._setRequestTask(distinctOptions); @@ -783,13 +817,11 @@ class ParseQuery { where: this._where, hint: this._hint, }; - return controller.aggregate( - this.className, - params, - distinctOptions - ).then((results) => { - return results.results; - }); + return controller + .aggregate(this.className, params, distinctOptions) + .then((results) => { + return results.results; + }); } /** @@ -808,15 +840,15 @@ class ParseQuery { const aggregateOptions = {}; aggregateOptions.useMasterKey = true; - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { aggregateOptions.sessionToken = options.sessionToken; } this._setRequestTask(aggregateOptions); const controller = CoreManager.getQueryController(); - if (!Array.isArray(pipeline) && typeof pipeline !== 'object') { - throw new Error('Invalid pipeline must be Array or Object'); + if (!Array.isArray(pipeline) && typeof pipeline !== "object") { + throw new Error("Invalid pipeline must be Array or Object"); } if (Object.keys(this._where || {}).length) { @@ -830,15 +862,13 @@ 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 results.results; - }); + return controller + .aggregate(this.className, params, aggregateOptions) + .then((results) => { + return results.results; + }); } /** @@ -861,13 +891,16 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { findOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { findOptions.context = options.context; } this._setRequestTask(findOptions); @@ -888,28 +921,26 @@ class ParseQuery { }); } - return controller.find( - this.className, - params, - findOptions - ).then((response) => { - const objects = response.results; - if (!objects[0]) { - return undefined; - } - if (!objects[0].className) { - objects[0].className = this.className; - } + return controller + .find(this.className, params, findOptions) + .then((response) => { + const objects = response.results; + if (!objects[0]) { + return undefined; + } + if (!objects[0].className) { + objects[0].className = this.className; + } - // Make sure the data object contains keys for all objects that - // have been requested with a select, so that our cached state - // updates correctly. - if (select) { - handleSelectResult(objects[0], select); - } + // Make sure the data object contains keys for all objects that + // have been requested with a select, so that our cached state + // updates correctly. + if (select) { + handleSelectResult(objects[0], select); + } - return ParseObject.fromJSON(objects[0], !select); - }); + return ParseObject.fromJSON(objects[0], !select); + }); } /** @@ -933,11 +964,14 @@ 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)) { - const error = 'Cannot iterate on a query with sort, skip, or limit.'; + if (this._order || this._skip || this._limit >= 0) { + const error = "Cannot iterate on a query with sort, skip, or limit."; return Promise.reject(error); } @@ -959,7 +993,7 @@ class ParseQuery { query._where[attr] = val.map((v) => { return v; }); - } else if (val && typeof val === 'object') { + } else if (val && typeof val === "object") { const conditionMap = {}; query._where[attr] = conditionMap; for (const cond in val) { @@ -970,38 +1004,46 @@ class ParseQuery { } } - query.ascending('objectId'); + query.ascending("objectId"); const findOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('sessionToken')) { + if (options.hasOwnProperty("sessionToken")) { findOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { + if ( + options.hasOwnProperty("context") && + typeof options.context === "object" + ) { findOptions.context = options.context; } 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; + } } - }); + ); } /** @@ -1023,7 +1065,10 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - each(callback: (obj: ParseObject) => any, options?: BatchOptions): Promise { + each( + callback: (obj: ParseObject) => any, + options?: BatchOptions + ): Promise { return this.eachBatch((results) => { let callbacksDone = Promise.resolve(); results.forEach((result) => { @@ -1042,7 +1087,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ hint(value: mixed): ParseQuery { - if (typeof value === 'undefined') { + if (typeof value === "undefined") { delete this._hint; } this._hint = value; @@ -1056,8 +1101,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ explain(explain: boolean = true): ParseQuery { - if (typeof explain !== 'boolean') { - throw new Error('You can only set explain to a boolean value'); + if (typeof explain !== "boolean") { + throw new Error("You can only set explain to a boolean value"); } this._explain = explain; return this; @@ -1086,7 +1131,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) => { @@ -1121,7 +1173,15 @@ 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) => { @@ -1132,15 +1192,19 @@ class ParseQuery { index += 1; return; } - return Promise.resolve(callback(accumulator, object, index)).then((result) => { - accumulator = result; - index += 1; - }); + return Promise.resolve(callback(accumulator, object, index)).then( + (result) => { + accumulator = result; + index += 1; + } + ); }, options); 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,7 +1232,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) => { @@ -1193,11 +1264,11 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ 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 + if (key && typeof key === "object") { + Object.entries(key).forEach(([k, val]) => this.equalTo(k, val)); + return this; } - if (typeof value === 'undefined') { + if (typeof value === "undefined") { return this.doesNotExist(key); } @@ -1214,11 +1285,11 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ 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 + if (key && typeof key === "object") { + Object.entries(key).forEach(([k, val]) => this.notEqualTo(k, val)); + return this; } - return this._addCondition(key, '$ne', value); + return this._addCondition(key, "$ne", value); } /** @@ -1230,7 +1301,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ lessThan(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$lt', value); + return this._addCondition(key, "$lt", value); } /** @@ -1242,7 +1313,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ greaterThan(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$gt', value); + return this._addCondition(key, "$gt", value); } /** @@ -1254,7 +1325,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ lessThanOrEqualTo(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$lte', value); + return this._addCondition(key, "$lte", value); } /** @@ -1266,7 +1337,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ greaterThanOrEqualTo(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$gte', value); + return this._addCondition(key, "$gte", value); } /** @@ -1278,7 +1349,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containedIn(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$in', value); + return this._addCondition(key, "$in", value); } /** @@ -1290,7 +1361,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ notContainedIn(key: string, value: mixed): ParseQuery { - return this._addCondition(key, '$nin', value); + return this._addCondition(key, "$nin", value); } /** @@ -1302,7 +1373,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containedBy(key: string, values: Array): ParseQuery { - return this._addCondition(key, '$containedBy', values); + return this._addCondition(key, "$containedBy", values); } /** @@ -1314,7 +1385,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containsAll(key: string, values: Array): ParseQuery { - return this._addCondition(key, '$all', values); + return this._addCondition(key, "$all", values); } /** @@ -1332,7 +1403,7 @@ class ParseQuery { } const regexObject = values.map((value) => { - return { '$regex': _this._regexStartWith(value) }; + return { $regex: _this._regexStartWith(value) }; }); return this.containsAll(key, regexObject); @@ -1345,7 +1416,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ exists(key: string): ParseQuery { - return this._addCondition(key, '$exists', true); + return this._addCondition(key, "$exists", true); } /** @@ -1355,7 +1426,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ doesNotExist(key: string): ParseQuery { - return this._addCondition(key, '$exists', false); + return this._addCondition(key, "$exists", false); } /** @@ -1369,18 +1440,18 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ matches(key: string, regex: RegExp, modifiers: string): ParseQuery { - this._addCondition(key, '$regex', regex); + this._addCondition(key, "$regex", regex); if (!modifiers) { - modifiers = ''; + modifiers = ""; } if (regex.ignoreCase) { - modifiers += 'i'; + modifiers += "i"; } if (regex.multiline) { - modifiers += 'm'; + modifiers += "m"; } if (modifiers.length) { - this._addCondition(key, '$options', modifiers); + this._addCondition(key, "$options", modifiers); } return this; } @@ -1397,7 +1468,7 @@ class ParseQuery { matchesQuery(key: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, '$inQuery', queryJSON); + return this._addCondition(key, "$inQuery", queryJSON); } /** @@ -1412,7 +1483,7 @@ class ParseQuery { doesNotMatchQuery(key: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, '$notInQuery', queryJSON); + return this._addCondition(key, "$notInQuery", queryJSON); } /** @@ -1426,12 +1497,16 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { + matchesKeyInQuery( + key: string, + queryKey: string, + query: ParseQuery + ): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, '$select', { + return this._addCondition(key, "$select", { key: queryKey, - query: queryJSON + query: queryJSON, }); } @@ -1446,12 +1521,16 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { + doesNotMatchKeyInQuery( + key: string, + queryKey: string, + query: ParseQuery + ): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, '$dontSelect', { + return this._addCondition(key, "$dontSelect", { key: queryKey, - query: queryJSON + query: queryJSON, }); } @@ -1464,10 +1543,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ contains(key: string, substring: string): ParseQuery { - if (typeof substring !== 'string') { - throw new Error('The value being searched for must be a string.'); + if (typeof substring !== "string") { + throw new Error("The value being searched for must be a string."); } - return this._addCondition(key, '$regex', quote(substring)); + return this._addCondition(key, "$regex", quote(substring)); } /** @@ -1503,13 +1582,13 @@ class ParseQuery { options = options || {}; if (!key) { - throw new Error('A key is required.'); + throw new Error("A key is required."); } if (!value) { - throw new Error('A search term is required'); + throw new Error("A search term is required"); } - if (typeof value !== 'string') { - throw new Error('The value being searched for must be a string.'); + if (typeof value !== "string") { + throw new Error("The value being searched for must be a string."); } const fullOptions = {}; @@ -1517,13 +1596,13 @@ class ParseQuery { for (const option in options) { switch (option) { - case 'language': + case "language": fullOptions.$language = options[option]; break; - case 'caseSensitive': + case "caseSensitive": fullOptions.$caseSensitive = options[option]; break; - case 'diacriticSensitive': + case "diacriticSensitive": fullOptions.$diacriticSensitive = options[option]; break; default: @@ -1531,7 +1610,7 @@ class ParseQuery { } } - return this._addCondition(key, '$text', { $search: fullOptions }); + return this._addCondition(key, "$text", { $search: fullOptions }); } /** @@ -1540,8 +1619,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ sortByTextScore() { - this.ascending('$score'); - this.select(['$score']); + this.ascending("$score"); + this.select(["$score"]); return this; } @@ -1555,10 +1634,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ startsWith(key: string, prefix: string): ParseQuery { - if (typeof prefix !== 'string') { - throw new Error('The value being searched for must be a string.'); + if (typeof prefix !== "string") { + throw new Error("The value being searched for must be a string."); } - return this._addCondition(key, '$regex', this._regexStartWith(prefix)); + return this._addCondition(key, "$regex", this._regexStartWith(prefix)); } /** @@ -1570,10 +1649,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ endsWith(key: string, suffix: string): ParseQuery { - if (typeof suffix !== 'string') { - throw new Error('The value being searched for must be a string.'); + if (typeof suffix !== "string") { + throw new Error("The value being searched for must be a string."); } - return this._addCondition(key, '$regex', quote(suffix) + '$'); + return this._addCondition(key, "$regex", quote(suffix) + "$"); } /** @@ -1589,7 +1668,7 @@ class ParseQuery { // Try to cast it as a GeoPoint point = new ParseGeoPoint(point); } - return this._addCondition(key, '$nearSphere', point); + return this._addCondition(key, "$nearSphere", point); } /** @@ -1604,12 +1683,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); + 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], + }); } } @@ -1626,7 +1712,12 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery { + withinMiles( + key: string, + point: ParseGeoPoint, + maxDistance: number, + sorted: boolean + ): ParseQuery { return this.withinRadians(key, point, maxDistance / 3958.8, sorted); } @@ -1643,7 +1734,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); } @@ -1659,14 +1755,18 @@ class ParseQuery { * The upper-right inclusive corner of the box. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): ParseQuery { + withinGeoBox( + key: string, + southwest: ParseGeoPoint, + northeast: ParseGeoPoint + ): ParseQuery { if (!(southwest instanceof ParseGeoPoint)) { southwest = new ParseGeoPoint(southwest); } 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 +1782,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 +1794,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 **/ @@ -1727,7 +1827,7 @@ class ParseQuery { if (Array.isArray(key)) { key = key.join(); } - this._order = this._order.concat(key.replace(/\s/g, '').split(',')); + this._order = this._order.concat(key.replace(/\s/g, "").split(",")); }); return this; @@ -1762,9 +1862,12 @@ class ParseQuery { 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; + }) ); }); @@ -1782,8 +1885,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ skip(n: number): ParseQuery { - if (typeof n !== 'number' || n < 0) { - throw new Error('You can only skip by a positive number'); + if (typeof n !== "number" || n < 0) { + throw new Error("You can only skip by a positive number"); } this._skip = n; return this; @@ -1796,8 +1899,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ limit(n: number): ParseQuery { - if (typeof n !== 'number') { - throw new Error('You can only set the limit to a numeric value'); + if (typeof n !== "number") { + throw new Error("You can only set the limit to a numeric value"); } this._limit = n; return this; @@ -1813,8 +1916,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ withCount(includeCount: boolean = true): ParseQuery { - if (typeof includeCount !== 'boolean') { - throw new Error('You can only set withCount to a boolean value'); + if (typeof includeCount !== "boolean") { + throw new Error("You can only set withCount to a boolean value"); } this._count = includeCount; return this; @@ -1830,7 +1933,7 @@ 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 { + include(...keys: Array>): ParseQuery { keys.forEach((key) => { if (Array.isArray(key)) { this._include = this._include.concat(key); @@ -1849,7 +1952,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ includeAll(): ParseQuery { - return this.include('*'); + return this.include("*"); } /** @@ -1860,7 +1963,7 @@ 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 = []; } @@ -1883,7 +1986,7 @@ 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 { + exclude(...keys: Array>): ParseQuery { keys.forEach((key) => { if (Array.isArray(key)) { this._exclude = this._exclude.concat(key); @@ -1902,7 +2005,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 +2026,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()) { @@ -2038,14 +2145,17 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ cancel(): ParseQuery { - if (this._xhrRequest.task && typeof this._xhrRequest.task.abort === 'function') { + if ( + this._xhrRequest.task && + typeof this._xhrRequest.task.abort === "function" + ) { this._xhrRequest.task._aborted = true; this._xhrRequest.task.abort(); this._xhrRequest.task = null; this._xhrRequest.onchange = () => {}; return this; } - return this._xhrRequest.onchange = () => this.cancel(); + return (this._xhrRequest.onchange = () => this.cancel()); } _setRequestTask(options) { @@ -2057,26 +2167,34 @@ class ParseQuery { } const DefaultController = { - find(className: string, params: QueryJSON, options: RequestOptions): Promise> { + find( + className: string, + params: QueryJSON, + options: RequestOptions + ): Promise> { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'GET', - 'classes/' + className, + "GET", + "classes/" + className, params, options ); }, - aggregate(className: string, params: any, options: RequestOptions): Promise> { + aggregate( + className: string, + params: any, + options: RequestOptions + ): Promise> { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'GET', - 'aggregate/' + className, + "GET", + "aggregate/" + className, params, options ); - } + }, }; CoreManager.setQueryController(DefaultController); diff --git a/src/ParseRelation.js b/src/ParseRelation.js index 6cb2b741e..d02ad774a 100644 --- a/src/ParseRelation.js +++ b/src/ParseRelation.js @@ -9,9 +9,9 @@ * @flow */ -import { RelationOp } from './ParseOp'; -import ParseObject from './ParseObject'; -import ParseQuery from './ParseQuery'; +import { RelationOp } from "./ParseOp"; +import ParseObject from "./ParseObject"; +import ParseQuery from "./ParseQuery"; /** * Creates a new Relation for the given parent object and key. This @@ -48,19 +48,19 @@ class ParseRelation { this.key = this.key || key; if (this.key !== key) { throw new Error( - 'Internal Error. Relation retrieved from two different keys.' + "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.' + "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.' + "Internal Error. Relation retrieved from two different Objects." ); } } else if (parent.id) { @@ -85,7 +85,7 @@ class ParseRelation { const change = new RelationOp(objects, []); const parent = this.parent; if (!parent) { - throw new Error('Cannot add to a Relation without a parent'); + throw new Error("Cannot add to a Relation without a parent"); } if (objects.length === 0) { return parent; @@ -107,7 +107,7 @@ class ParseRelation { const change = new RelationOp([], objects); if (!this.parent) { - throw new Error('Cannot remove from a Relation without a parent'); + throw new Error("Cannot remove from a Relation without a parent"); } if (objects.length === 0) { return; @@ -121,10 +121,10 @@ class ParseRelation { * * @returns {object} JSON representation of Relation */ - toJSON(): { __type: 'Relation', className: ?string } { + toJSON(): { __type: "Relation", className: ?string } { return { - __type: 'Relation', - className: this.targetClassName + __type: "Relation", + className: this.targetClassName, }; } @@ -138,20 +138,22 @@ class ParseRelation { let query; const parent = this.parent; if (!parent) { - throw new Error('Cannot construct a query for a Relation without a parent'); + throw new Error( + "Cannot construct a query for a Relation without a parent" + ); } if (!this.targetClassName) { 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', + query._addCondition("$relatedTo", "object", { + __type: "Pointer", className: parent.className, - objectId: parent.id + objectId: parent.id, }); - query._addCondition('$relatedTo', 'key', this.key); + query._addCondition("$relatedTo", "key", this.key); return query; } diff --git a/src/ParseRole.js b/src/ParseRole.js index 72fcfd2f4..1ee691b72 100644 --- a/src/ParseRole.js +++ b/src/ParseRole.js @@ -9,12 +9,12 @@ * @flow */ -import ParseACL from './ParseACL'; -import ParseError from './ParseError'; -import ParseObject from './ParseObject'; +import ParseACL from "./ParseACL"; +import ParseError from "./ParseError"; +import ParseObject from "./ParseObject"; -import type { AttributeMap } from './ObjectStateMutations'; -import type ParseRelation from './ParseRelation'; +import type { AttributeMap } from "./ObjectStateMutations"; +import type ParseRelation from "./ParseRelation"; /** * Represents a Role on the Parse server. Roles represent groupings of @@ -37,8 +37,8 @@ class ParseRole extends ParseObject { * cloud. */ constructor(name: string, acl: ParseACL) { - super('_Role'); - if (typeof name === 'string' && (acl instanceof ParseACL)) { + super("_Role"); + if (typeof name === "string" && acl instanceof ParseACL) { this.setName(name); this.setACL(acl); } @@ -50,11 +50,11 @@ class ParseRole extends ParseObject { * @returns {string} the name of the role. */ getName(): ?string { - const name = this.get('name'); - if (name == null || typeof name === 'string') { + const name = this.get("name"); + if (name == null || typeof name === "string") { return name; } - return ''; + return ""; } /** @@ -75,7 +75,7 @@ class ParseRole extends ParseObject { * @returns {(ParseObject|boolean)} true if the set succeeded. */ setName(name: string, options?: mixed): ParseObject | boolean { - return this.set('name', name, options); + return this.set("name", name, options); } /** @@ -90,7 +90,7 @@ class ParseRole extends ParseObject { * role. */ getUsers(): ParseRelation { - return this.relation('users'); + return this.relation("users"); } /** @@ -105,7 +105,7 @@ class ParseRole extends ParseObject { * role. */ getRoles(): ParseRelation { - return this.relation('roles'); + return this.relation("roles"); } validate(attrs: AttributeMap, options?: mixed): ParseError | boolean { @@ -114,7 +114,7 @@ class ParseRole extends ParseObject { return isInvalid; } - if ('name' in attrs && attrs.name !== this.getName()) { + if ("name" in attrs && attrs.name !== this.getName()) { const newName = attrs.name; if (this.id && this.id !== attrs.objectId) { // Check to see if the objectId being set matches this.id @@ -122,20 +122,20 @@ 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') { + if (typeof newName !== "string") { return new ParseError( ParseError.OTHER_CAUSE, - 'A role\'s name must be a String.' + "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." ); } } @@ -143,6 +143,6 @@ class ParseRole extends ParseObject { } } -ParseObject.registerSubclass('_Role', ParseRole); +ParseObject.registerSubclass("_Role", ParseRole); export default ParseRole; diff --git a/src/ParseSchema.js b/src/ParseSchema.js index 227d7cb20..4e89fb47f 100644 --- a/src/ParseSchema.js +++ b/src/ParseSchema.js @@ -9,14 +9,26 @@ * @flow */ -import CoreManager from './CoreManager'; -import ParseObject from './ParseObject'; - -const FIELD_TYPES = ['String', 'Number', 'Boolean', 'Date', 'File', 'GeoPoint', 'Polygon', 'Array', 'Object', 'Pointer', 'Relation']; +import CoreManager from "./CoreManager"; +import ParseObject from "./ParseObject"; + +const FIELD_TYPES = [ + "String", + "Number", + "Boolean", + "Date", + "File", + "GeoPoint", + "Polygon", + "Array", + "Object", + "Pointer", + "Relation", +]; type FieldOptions = { - required: boolean; - defaultValue: mixed; + required: boolean, + defaultValue: mixed, }; /** @@ -46,9 +58,9 @@ class ParseSchema { * @param {string} className Parse Class string. */ constructor(className: string) { - if (typeof className === 'string') { - if (className === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { - this.className = '_User'; + if (typeof className === "string") { + if (className === "User" && CoreManager.get("PERFORM_USER_REWRITE")) { + this.className = "_User"; } else { this.className = className; } @@ -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; + }); } /** @@ -172,7 +182,7 @@ class ParseSchema { */ assertClassName() { if (!this.className) { - throw new Error('You must set a Class Name before making any request.'); + throw new Error("You must set a Class Name before making any request."); } } @@ -201,17 +211,17 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addField(name: string, type: string, options: FieldOptions = {}) { - type = type || 'String'; + type = type || "String"; if (!name) { - throw new Error('field name may not be null.'); + throw new Error("field name may not be null."); } if (FIELD_TYPES.indexOf(type) === -1) { throw new Error(`${type} is not a valid type.`); } const fieldOptions = { type }; - if (typeof options.required === 'boolean') { + if (typeof options.required === "boolean") { fieldOptions.required = options.required; } if (options.defaultValue !== undefined) { @@ -234,10 +244,10 @@ class ParseSchema { */ addIndex(name: string, index: any) { if (!name) { - throw new Error('index name may not be null.'); + throw new Error("index name may not be null."); } if (!index) { - throw new Error('index may not be null.'); + throw new Error("index may not be null."); } this._indexes[name] = index; @@ -253,7 +263,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addString(name: string, options: FieldOptions) { - return this.addField(name, 'String', options); + return this.addField(name, "String", options); } /** @@ -264,7 +274,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addNumber(name: string, options: FieldOptions) { - return this.addField(name, 'Number', options); + return this.addField(name, "Number", options); } /** @@ -275,7 +285,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addBoolean(name: string, options: FieldOptions) { - return this.addField(name, 'Boolean', options); + return this.addField(name, "Boolean", options); } /** @@ -287,9 +297,12 @@ 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); + return this.addField(name, "Date", options); } /** @@ -300,7 +313,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addFile(name: string, options: FieldOptions) { - return this.addField(name, 'File', options); + return this.addField(name, "File", options); } /** @@ -311,7 +324,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addGeoPoint(name: string, options: FieldOptions) { - return this.addField(name, 'GeoPoint', options); + return this.addField(name, "GeoPoint", options); } /** @@ -322,7 +335,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addPolygon(name: string, options: FieldOptions) { - return this.addField(name, 'Polygon', options); + return this.addField(name, "Polygon", options); } /** @@ -333,7 +346,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addArray(name: string, options: FieldOptions) { - return this.addField(name, 'Array', options); + return this.addField(name, "Array", options); } /** @@ -344,7 +357,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addObject(name: string, options: FieldOptions) { - return this.addField(name, 'Object', options); + return this.addField(name, "Object", options); } /** @@ -357,14 +370,14 @@ class ParseSchema { */ addPointer(name: string, targetClass: string, options: FieldOptions = {}) { if (!name) { - throw new Error('field name may not be null.'); + throw new Error("field name may not be null."); } if (!targetClass) { - throw new Error('You need to set the targetClass of the Pointer.'); + throw new Error("You need to set the targetClass of the Pointer."); } - const fieldOptions = { type: 'Pointer', targetClass }; + const fieldOptions = { type: "Pointer", targetClass }; - if (typeof options.required === 'boolean') { + if (typeof options.required === "boolean") { fieldOptions.required = options.required; } if (options.defaultValue !== undefined) { @@ -386,15 +399,15 @@ class ParseSchema { */ addRelation(name: string, targetClass: string) { if (!name) { - throw new Error('field name may not be null.'); + throw new Error("field name may not be null."); } if (!targetClass) { - throw new Error('You need to set the targetClass of the Relation.'); + throw new Error("You need to set the targetClass of the Relation."); } this._fields[name] = { - type: 'Relation', - targetClass + type: "Relation", + 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,39 +439,36 @@ 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 { - return this.send(className, 'GET'); + return this.send(className, "GET"); }, create(className: string, params: any): Promise { - return this.send(className, 'POST', params); + return this.send(className, "POST", params); }, update(className: string, params: any): Promise { - return this.send(className, 'PUT', params); + return this.send(className, "PUT", params); }, delete(className: string): Promise { - return this.send(className, 'DELETE'); + return this.send(className, "DELETE"); }, purge(className: string): Promise { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'DELETE', + "DELETE", `purge/${className}`, {}, { useMasterKey: true } ); - } + }, }; CoreManager.setSchemaController(DefaultController); diff --git a/src/ParseSession.js b/src/ParseSession.js index 561309d64..7590e92e7 100644 --- a/src/ParseSession.js +++ b/src/ParseSession.js @@ -9,13 +9,13 @@ * @flow */ -import CoreManager from './CoreManager'; -import isRevocableSession from './isRevocableSession'; -import ParseObject from './ParseObject'; -import ParseUser from './ParseUser'; +import CoreManager from "./CoreManager"; +import isRevocableSession from "./isRevocableSession"; +import ParseObject from "./ParseObject"; +import ParseUser from "./ParseUser"; -import type { AttributeMap } from './ObjectStateMutations'; -import type { RequestOptions, FullOptions } from './RESTController'; +import type { AttributeMap } from "./ObjectStateMutations"; +import type { RequestOptions, FullOptions } from "./RESTController"; /** *

A Parse.Session object is a local representation of a revocable session. @@ -30,10 +30,10 @@ class ParseSession extends ParseObject { * @param {object} attributes The initial set of data to store in the user. */ constructor(attributes: ?AttributeMap) { - super('_Session'); - if (attributes && typeof attributes === 'object'){ + super("_Session"); + 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"); } } } @@ -44,21 +44,21 @@ class ParseSession extends ParseObject { * @returns {string} */ getSessionToken(): string { - const token = this.get('sessionToken'); - if (typeof token === 'string') { + const token = this.get("sessionToken"); + if (typeof token === "string") { return token; } - return ''; + return ""; } static readOnlyAttributes() { return [ - 'createdWith', - 'expiresAt', - 'installationId', - 'restricted', - 'sessionToken', - 'user' + "createdWith", + "expiresAt", + "installationId", + "restricted", + "sessionToken", + "user", ]; } @@ -76,12 +76,12 @@ class ParseSession extends ParseObject { const controller = CoreManager.getSessionController(); const sessionOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { sessionOptions.useMasterKey = options.useMasterKey; } return ParseUser.currentAsync().then((user) => { if (!user) { - return Promise.reject('There is no current user.'); + return Promise.reject("There is no current user."); } sessionOptions.sessionToken = user.getSessionToken(); return controller.getSession(sessionOptions); @@ -101,27 +101,27 @@ class ParseSession extends ParseObject { static isCurrentSessionRevocable(): boolean { const currentUser = ParseUser.current(); if (currentUser) { - return isRevocableSession(currentUser.getSessionToken() || ''); + return isRevocableSession(currentUser.getSessionToken() || ""); } return false; } } -ParseObject.registerSubclass('_Session', ParseSession); +ParseObject.registerSubclass("_Session", ParseSession); const DefaultController = { getSession(options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); const session = new ParseSession(); - return RESTController.request( - 'GET', 'sessions/me', {}, options - ).then((sessionData) => { - session._finishFetch(sessionData); - session._setExisted(true); - return session; - }); - } + 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..fd990f48b 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -9,21 +9,21 @@ * @flow */ -import AnonymousUtils from './AnonymousUtils'; -import CoreManager from './CoreManager'; -import isRevocableSession from './isRevocableSession'; -import ParseError from './ParseError'; -import ParseObject from './ParseObject'; -import ParseSession from './ParseSession'; -import Storage from './Storage'; +import AnonymousUtils from "./AnonymousUtils"; +import CoreManager from "./CoreManager"; +import isRevocableSession from "./isRevocableSession"; +import ParseError from "./ParseError"; +import ParseObject from "./ParseObject"; +import ParseSession from "./ParseSession"; +import Storage from "./Storage"; -import type { AttributeMap } from './ObjectStateMutations'; -import type { RequestOptions, FullOptions } from './RESTController'; +import type { AttributeMap } from "./ObjectStateMutations"; +import type { RequestOptions, FullOptions } from "./RESTController"; export type AuthData = ?{ [key: string]: mixed }; -const CURRENT_USER_KEY = 'currentUser'; -let canUseCurrentUser = !CoreManager.get('IS_NODE'); +const CURRENT_USER_KEY = "currentUser"; +let canUseCurrentUser = !CoreManager.get("IS_NODE"); let currentUserCacheMatchesDisk = false; let currentUserCache = null; @@ -44,10 +44,10 @@ class ParseUser extends ParseObject { * @param {object} attributes The initial set of data to store in the user. */ constructor(attributes: ?AttributeMap) { - super('_User'); - if (attributes && typeof attributes === 'object'){ + super("_User"); + 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"); } } } @@ -63,15 +63,12 @@ class ParseUser extends ParseObject { options = options || {}; const upgradeOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { upgradeOptions.useMasterKey = options.useMasterKey; } const controller = CoreManager.getUserController(); - return controller.upgradeToRevocableSession( - this, - upgradeOptions - ); + return controller.upgradeToRevocableSession(this, upgradeOptions); } /** @@ -89,10 +86,15 @@ 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 { - saveOpts.sessionToken = saveOpts.sessionToken || this.getSessionToken() || ''; + linkWith( + provider: any, + options: { authData?: AuthData }, + saveOpts?: FullOptions = {} + ): Promise { + saveOpts.sessionToken = + saveOpts.sessionToken || this.getSessionToken() || ""; let authType; - if (typeof provider === 'string') { + if (typeof provider === "string") { authType = provider; if (authProviders[provider]) { provider = authProviders[provider]; @@ -111,34 +113,33 @@ class ParseUser extends ParseObject { } else { authType = provider.getAuthType(); } - if (options && options.hasOwnProperty('authData')) { - const authData = this.get('authData') || {}; - if (typeof authData !== 'object') { - throw new Error('Invalid type: authData field should be an object'); + if (options && options.hasOwnProperty("authData")) { + const authData = this.get("authData") || {}; + if (typeof authData !== "object") { + throw new Error("Invalid type: authData field should be an object"); } 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 +152,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); } @@ -166,14 +171,14 @@ class ParseUser extends ParseObject { return; } let authType; - if (typeof provider === 'string') { + if (typeof provider === "string") { authType = provider; provider = authProviders[authType]; } else { authType = provider.getAuthType(); } - const authData = this.get('authData'); - if (!provider || !authData || typeof authData !== 'object') { + const authData = this.get("authData"); + if (!provider || !authData || typeof authData !== "object") { return; } const success = provider.restoreAuthentication(authData[authType]); @@ -186,8 +191,8 @@ class ParseUser extends ParseObject { * Synchronizes authData for all providers. */ _synchronizeAllAuthData() { - const authData = this.get('authData'); - if (typeof authData !== 'object') { + const authData = this.get("authData"); + if (typeof authData !== "object") { return; } @@ -203,8 +208,8 @@ class ParseUser extends ParseObject { if (!this.isCurrent()) { return; } - const authData = this.get('authData'); - if (typeof authData !== 'object') { + const authData = this.get("authData"); + if (typeof authData !== "object") { return; } @@ -238,13 +243,13 @@ class ParseUser extends ParseObject { */ _isLinked(provider: any): boolean { let authType; - if (typeof provider === 'string') { + if (typeof provider === "string") { authType = provider; } else { authType = provider.getAuthType(); } - const authData = this.get('authData') || {}; - if (typeof authData !== 'object') { + const authData = this.get("authData") || {}; + if (typeof authData !== "object") { return false; } return !!authData[authType]; @@ -254,8 +259,8 @@ class ParseUser extends ParseObject { * Deauthenticates all providers. */ _logOutWithAll() { - const authData = this.get('authData'); - if (typeof authData !== 'object') { + const authData = this.get("authData"); + if (typeof authData !== "object") { return; } @@ -274,7 +279,7 @@ class ParseUser extends ParseObject { if (!this.isCurrent()) { return; } - if (typeof provider === 'string') { + if (typeof provider === "string") { provider = authProviders[provider]; } if (provider && provider.deauthenticate) { @@ -290,7 +295,7 @@ class ParseUser extends ParseObject { */ _preserveFieldsOnFetch(): AttributeMap { return { - sessionToken: this.get('sessionToken'), + sessionToken: this.get("sessionToken"), }; } @@ -310,11 +315,11 @@ class ParseUser extends ParseObject { * @returns {string} */ getUsername(): ?string { - const username = this.get('username'); - if (username == null || typeof username === 'string') { + const username = this.get("username"); + if (username == null || typeof username === "string") { return username; } - return ''; + return ""; } /** @@ -325,12 +330,16 @@ class ParseUser extends ParseObject { setUsername(username: string) { // Strip anonymity, even we do not support anonymous user in js SDK, we may // encounter anonymous user created by android/iOS in cloud code. - const authData = this.get('authData'); - if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) { + const authData = this.get("authData"); + if ( + authData && + typeof authData === "object" && + authData.hasOwnProperty("anonymous") + ) { // We need to set anonymous to null instead of deleting it in order to remove it from Parse. authData.anonymous = null; } - this.set('username', username); + this.set("username", username); } /** @@ -339,7 +348,7 @@ class ParseUser extends ParseObject { * @param {string} password User's Password */ setPassword(password: string) { - this.set('password', password); + this.set("password", password); } /** @@ -348,11 +357,11 @@ class ParseUser extends ParseObject { * @returns {string} User's Email */ getEmail(): ?string { - const email = this.get('email'); - if (email == null || typeof email === 'string') { + const email = this.get("email"); + if (email == null || typeof email === "string") { return email; } - return ''; + return ""; } /** @@ -362,7 +371,7 @@ class ParseUser extends ParseObject { * @returns {boolean} */ setEmail(email: string) { - return this.set('email', email); + return this.set("email", email); } /** @@ -373,11 +382,11 @@ class ParseUser extends ParseObject { * @returns {string} the session token, or undefined */ getSessionToken(): ?string { - const token = this.get('sessionToken'); - if (token == null || typeof token === 'string') { + const token = this.get("sessionToken"); + if (token == null || typeof token === "string") { return token; } - return ''; + return ""; } /** @@ -387,11 +396,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; } /** @@ -411,19 +416,15 @@ class ParseUser extends ParseObject { options = options || {}; const signupOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { signupOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('installationId')) { + if (options.hasOwnProperty("installationId")) { signupOptions.installationId = options.installationId; } const controller = CoreManager.getUserController(); - return controller.signUp( - this, - attrs, - signupOptions - ); + return controller.signUp(this, attrs, signupOptions); } /** @@ -441,13 +442,13 @@ class ParseUser extends ParseObject { options = options || {}; const loginOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { loginOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty('installationId')) { + if (options.hasOwnProperty("installationId")) { loginOptions.installationId = options.installationId; } - if (options.hasOwnProperty('usePost')) { + if (options.hasOwnProperty("usePost")) { loginOptions.usePost = options.usePost; } @@ -527,14 +528,17 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with a user * when the password is correct. */ - verifyPassword(password: string, options?: RequestOptions): Promise { - const username = this.getUsername() || ''; + verifyPassword( + password: string, + options?: RequestOptions + ): Promise { + const username = this.getUsername() || ""; return ParseUser.verifyPassword(username, password, options); } static readOnlyAttributes() { - return ['sessionToken']; + return ["sessionToken"]; } /** @@ -545,15 +549,18 @@ 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') { + if (prop !== "className") { Object.defineProperty(ParseUser.prototype, prop, { value: protoProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -561,12 +568,12 @@ class ParseUser extends ParseObject { if (classProps) { for (const prop in classProps) { - if (prop !== 'className') { + if (prop !== "className") { Object.defineProperty(ParseUser, prop, { value: classProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -619,7 +626,12 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the signup completes. */ - static signUp(username: string, password: string, attrs: AttributeMap, options?: FullOptions) { + static signUp( + username: string, + password: string, + attrs: AttributeMap, + options?: FullOptions + ) { attrs = attrs || {}; attrs.username = username; attrs.password = password; @@ -640,19 +652,13 @@ class ParseUser extends ParseObject { * the login completes. */ static logIn(username: string, password: string, options?: FullOptions) { - if (typeof username !== 'string') { + if (typeof username !== "string") { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Username must be a string.' - ) + new ParseError(ParseError.OTHER_CAUSE, "Username must be a string.") ); - } else if (typeof password !== 'string') { + } else if (typeof password !== "string") { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Password must be a string.' - ) + new ParseError(ParseError.OTHER_CAUSE, "Password must be a string.") ); } const user = new this(); @@ -674,15 +680,15 @@ 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' + "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')) { + if (options.hasOwnProperty("useMasterKey")) { becomeOptions.useMasterKey = options.useMasterKey; } @@ -702,7 +708,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 +742,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); } @@ -771,14 +781,12 @@ class ParseUser extends ParseObject { options = options || {}; const requestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { requestOptions.useMasterKey = options.useMasterKey; } const controller = CoreManager.getUserController(); - return controller.requestPasswordReset( - email, requestOptions - ); + return controller.requestPasswordReset(email, requestOptions); } /** @@ -794,7 +802,7 @@ class ParseUser extends ParseObject { options = options || {}; const requestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { requestOptions.useMasterKey = options.useMasterKey; } @@ -812,29 +820,27 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with a user * when the password is correct. */ - static verifyPassword(username: string, password: string, options?: RequestOptions) { - if (typeof username !== 'string') { + 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.' - ) + new ParseError(ParseError.OTHER_CAUSE, "Username must be a string.") ); } - if (typeof password !== 'string') { + if (typeof password !== "string") { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Password must be a string.' - ) + new ParseError(ParseError.OTHER_CAUSE, "Password must be a string.") ); } options = options || {}; const verificationOption = {}; - if (options.hasOwnProperty('useMasterKey')) { + if (options.hasOwnProperty("useMasterKey")) { verificationOption.useMasterKey = options.useMasterKey; } @@ -852,7 +858,7 @@ class ParseUser extends ParseObject { * @static */ static allowCustomUserClass(isAllowed: boolean) { - CoreManager.set('PERFORM_USER_REWRITE', !isAllowed); + CoreManager.set("PERFORM_USER_REWRITE", !isAllowed); } /** @@ -871,7 +877,7 @@ class ParseUser extends ParseObject { */ static enableRevocableSession(options?: RequestOptions) { options = options || {}; - CoreManager.set('FORCE_REVOCABLE_SESSION', true); + CoreManager.set("FORCE_REVOCABLE_SESSION", true); if (canUseCurrentUser) { const current = ParseUser.current(); if (current) { @@ -933,7 +939,11 @@ class ParseUser extends ParseObject { * @static * @returns {Promise} */ - static _logInWith(provider: any, options: { authData?: AuthData }, saveOpts?: FullOptions) { + static _logInWith( + provider: any, + options: { authData?: AuthData }, + saveOpts?: FullOptions + ) { const user = new this(); return user.linkWith(provider, options, saveOpts); } @@ -948,7 +958,7 @@ class ParseUser extends ParseObject { } } -ParseObject.registerSubclass('_User', ParseUser); +ParseObject.registerSubclass("_User", ParseUser); const DefaultController = { updateUserOnDisk(user) { @@ -956,15 +966,13 @@ const DefaultController = { const json = user.toJSON(); delete json.password; - json.className = '_User'; + json.className = "_User"; let userData = JSON.stringify(json); - if (CoreManager.get('ENCRYPTED_USER')) { + 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; }); }, @@ -978,8 +986,14 @@ const DefaultController = { async setCurrentUser(user) { const currentUser = await this.currentUserAsync(); - if (currentUser && !user.equals(currentUser) && AnonymousUtils.isLinked(currentUser)) { - await currentUser.destroy({ sessionToken: currentUser.getSessionToken() }) + if ( + currentUser && + !user.equals(currentUser) && + AnonymousUtils.isLinked(currentUser) + ) { + await currentUser.destroy({ + sessionToken: currentUser.getSessionToken(), + }); } currentUserCache = user; user._cleanupAuthData(); @@ -996,8 +1010,8 @@ const DefaultController = { } if (Storage.async()) { throw new Error( - 'Cannot call currentUser() when using a platform with an async ' + - 'storage system. Call currentUserAsync() instead.' + "Cannot call currentUser() when using a platform with an async " + + "storage system. Call currentUserAsync() instead." ); } const path = Storage.generatePath(CURRENT_USER_KEY); @@ -1007,13 +1021,13 @@ const DefaultController = { currentUserCache = null; return null; } - if (CoreManager.get('ENCRYPTED_USER')) { + if (CoreManager.get("ENCRYPTED_USER")) { const crypto = CoreManager.getCryptoController(); - userData = crypto.decrypt(userData, CoreManager.get('ENCRYPTED_KEY')); + userData = crypto.decrypt(userData, CoreManager.get("ENCRYPTED_KEY")); } userData = JSON.parse(userData); if (!userData.className) { - userData.className = '_User'; + userData.className = "_User"; } if (userData._id) { if (userData.objectId !== userData._id) { @@ -1033,27 +1047,28 @@ 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; return Promise.resolve(null); } - if (CoreManager.get('ENCRYPTED_USER')) { + if (CoreManager.get("ENCRYPTED_USER")) { const crypto = CoreManager.getCryptoController(); - userData = crypto.decrypt(userData.toString(), CoreManager.get('ENCRYPTED_KEY')); + userData = crypto.decrypt( + userData.toString(), + CoreManager.get("ENCRYPTED_KEY") + ); } userData = JSON.parse(userData); if (!userData.className) { - userData.className = '_User'; + userData.className = "_User"; } if (userData._id) { if (userData.objectId !== userData._id) { @@ -1072,15 +1087,19 @@ const DefaultController = { }); }, - signUp(user: ParseUser, attrs: AttributeMap, options: RequestOptions): Promise { - const username = (attrs && attrs.username) || user.get('username'); - const password = (attrs && attrs.password) || user.get('password'); + signUp( + user: ParseUser, + attrs: AttributeMap, + options: RequestOptions + ): Promise { + const username = (attrs && attrs.username) || user.get("username"); + const password = (attrs && attrs.password) || user.get("password"); if (!username || !username.length) { return Promise.reject( new ParseError( ParseError.OTHER_CAUSE, - 'Cannot sign up user with an empty username.' + "Cannot sign up user with an empty username." ) ); } @@ -1088,7 +1107,7 @@ const DefaultController = { return Promise.reject( new ParseError( ParseError.OTHER_CAUSE, - 'Cannot sign up user with an empty password.' + "Cannot sign up user with an empty password." ) ); } @@ -1108,19 +1127,26 @@ const DefaultController = { const RESTController = CoreManager.getRESTController(); const stateController = CoreManager.getObjectStateController(); const auth = { - username: user.get('username'), - password: user.get('password') + username: user.get("username"), + password: user.get("password"), }; return RESTController.request( - options.usePost ? 'POST' : 'GET', 'login', auth, options + options.usePost ? "POST" : "GET", + "login", + auth, + options ).then((response) => { user._migrateId(response.objectId); user._setExisted(true); stateController.setPendingOp( - user._getStateIdentifier(), 'username', undefined + user._getStateIdentifier(), + "username", + undefined ); stateController.setPendingOp( - user._getStateIdentifier(), 'password', undefined + user._getStateIdentifier(), + "password", + undefined ); response.password = undefined; user._finishFetch(response); @@ -1134,13 +1160,13 @@ const DefaultController = { become(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'users/me', {}, options - ).then((response) => { - user._finishFetch(response); - user._setExisted(true); - return DefaultController.setCurrentUser(user); - }); + return RESTController.request("GET", "users/me", {}, options).then( + (response) => { + user._finishFetch(response); + user._setExisted(true); + return DefaultController.setCurrentUser(user); + } + ); }, hydrate(user: ParseUser, userJSON: AttributeMap): Promise { @@ -1155,21 +1181,19 @@ const DefaultController = { me(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'users/me', {}, options - ).then((response) => { - user._finishFetch(response); - user._setExisted(true); - return user; - }); + return RESTController.request("GET", "users/me", {}, options).then( + (response) => { + user._finishFetch(response); + user._setExisted(true); + return user; + } + ); }, 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) => { const path = Storage.generatePath(CURRENT_USER_KEY); @@ -1178,15 +1202,20 @@ const DefaultController = { 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 }); @@ -1201,8 +1230,8 @@ const DefaultController = { requestPasswordReset(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'POST', - 'requestPasswordReset', + "POST", + "requestPasswordReset", { email: email }, options ); @@ -1214,7 +1243,7 @@ const DefaultController = { return Promise.reject( new ParseError( ParseError.SESSION_MISSING, - 'Cannot upgrade a user with no session token' + "Cannot upgrade a user with no session token" ) ); } @@ -1223,8 +1252,8 @@ const DefaultController = { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'POST', - 'upgradeToRevocableSession', + "POST", + "upgradeToRevocableSession", {}, options ).then((result) => { @@ -1250,8 +1279,8 @@ const DefaultController = { verifyPassword(username: string, password: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'GET', - 'verifyPassword', + "GET", + "verifyPassword", { username, password }, options ); @@ -1260,12 +1289,12 @@ const DefaultController = { requestEmailVerification(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); return RESTController.request( - 'POST', - 'verificationEmailRequest', + "POST", + "verificationEmailRequest", { email: email }, options ); - } + }, }; CoreManager.setUserController(DefaultController); diff --git a/src/Push.js b/src/Push.js index 6e7c5be98..608bd04ce 100644 --- a/src/Push.js +++ b/src/Push.js @@ -9,16 +9,16 @@ * @flow */ -import CoreManager from './CoreManager'; -import ParseQuery from './ParseQuery'; +import CoreManager from "./CoreManager"; +import ParseQuery from "./ParseQuery"; -import type { WhereClause } 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, }; /** @@ -57,17 +57,17 @@ export function send(data: PushData): Promise { data.where = data.where.toJSON().where; } - if (data.push_time && typeof data.push_time === 'object') { + if (data.push_time && typeof data.push_time === "object") { data.push_time = data.push_time.toJSON(); } - if (data.expiration_time && typeof data.expiration_time === 'object') { + if (data.expiration_time && typeof data.expiration_time === "object") { data.expiration_time = data.expiration_time.toJSON(); } if (data.expiration_time && data.expiration_interval) { throw new Error( - 'expiration_time and expiration_interval cannot both be set.' + "expiration_time and expiration_interval cannot both be set." ); } @@ -76,13 +76,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..7669e7e38 100644 --- a/src/RESTController.js +++ b/src/RESTController.js @@ -9,55 +9,63 @@ * @flow */ /* global XMLHttpRequest, XDomainRequest */ -const uuidv4 = require('uuid/v4'); +const uuidv4 = require("uuid/v4"); -import CoreManager from './CoreManager'; -import ParseError from './ParseError'; -import { resolvingPromise } from './promiseUtils'; +import CoreManager from "./CoreManager"; +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; -if (typeof XMLHttpRequest !== 'undefined') { +if (typeof XMLHttpRequest !== "undefined") { XHR = XMLHttpRequest; } -if (process.env.PARSE_BUILD === 'node') { - XHR = require('xmlhttprequest').XMLHttpRequest; +if (process.env.PARSE_BUILD === "node") { + XHR = require("xmlhttprequest").XMLHttpRequest; } -if (process.env.PARSE_BUILD === 'weapp') { - XHR = require('./Xhr.weapp'); +if (process.env.PARSE_BUILD === "weapp") { + XHR = require("./Xhr.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) { +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,49 +76,56 @@ 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); } }; xdr.open(method, url); xdr.send(data); - if (options && typeof options.requestTask === 'function') { + if (options && typeof options.requestTask === "function") { options.requestTask(xdr); } }); } const RESTController = { - ajax(method: string, url: string, data: any, headers?: any, options?: FullOptions) { + ajax( + method: string, + url: string, + data: any, + headers?: any, + options?: FullOptions + ) { if (useXDomainRequest) { return ajaxIE9(method, url, data, headers, options); } const promise = resolvingPromise(); - const isIdempotent = CoreManager.get('IDEMPOTENCY') && ['POST', 'PUT'].includes(method); - const requestId = isIdempotent ? uuidv4() : ''; + const isIdempotent = + CoreManager.get("IDEMPOTENCY") && ["POST", "PUT"].includes(method); + 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.' + "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; } @@ -121,9 +136,13 @@ const RESTController = { try { response = JSON.parse(xhr.responseText); - if (typeof xhr.getResponseHeader === 'function') { - if ((xhr.getAllResponseHeaders() || '').includes('x-parse-job-status-id: ')) { - response = xhr.getResponseHeader('x-parse-job-status-id'); + if (typeof xhr.getResponseHeader === "function") { + if ( + (xhr.getAllResponseHeaders() || "").includes( + "x-parse-job-status-id: " + ) + ) { + response = xhr.getResponseHeader("x-parse-job-status-id"); } } } catch (e) { @@ -132,15 +151,16 @@ 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 - if (++attempts < CoreManager.get('REQUEST_ATTEMPT_LIMIT')) { + } 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) ); setTimeout(dispatch, delay); } else if (xhr.status === 0) { - promise.reject('Unable to connect to the Parse API'); + promise.reject("Unable to connect to the Parse API"); } else { // After the retry limit is reached, fail promise.reject(xhr); @@ -151,26 +171,36 @@ const RESTController = { }; headers = headers || {}; - if (typeof(headers['Content-Type']) !== 'string') { - headers['Content-Type'] = 'text/plain'; // Avoid pre-flight + 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 + ')'; + if (CoreManager.get("IS_NODE")) { + headers["User-Agent"] = + "Parse/" + + CoreManager.get("VERSION") + + " (NodeJS " + + process.versions.node + + ")"; } if (isIdempotent) { - headers['X-Parse-Request-Id'] = requestId; + 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'); + if ( + 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'); + const customHeaders = CoreManager.get("REQUEST_HEADERS"); for (const key in customHeaders) { headers[key] = customHeaders[key]; } function handleProgress(type, event) { - if (options && typeof options.progress === 'function') { + if (options && typeof options.progress === "function") { if (event.lengthComputable) { options.progress( event.loaded / event.total, @@ -185,13 +215,13 @@ const RESTController = { } xhr.onprogress = (event) => { - handleProgress('download', event); + handleProgress("download", event); }; if (xhr.upload) { xhr.upload.onprogress = (event) => { - handleProgress('upload', event); - } + handleProgress("upload", event); + }; } xhr.open(method, url, true); @@ -208,10 +238,10 @@ const RESTController = { }; xhr.send(data); - if (options && typeof options.requestTask === 'function') { + if (options && typeof options.requestTask === "function") { options.requestTask(xhr); } - } + }; dispatch(); return promise; @@ -219,14 +249,14 @@ const RESTController = { request(method: string, path: string, data: mixed, options?: RequestOptions) { options = options || {}; - let url = CoreManager.get('SERVER_URL'); - if (url[url.length - 1] !== '/') { - url += '/'; + let url = CoreManager.get("SERVER_URL"); + if (url[url.length - 1] !== "/") { + url += "/"; } url += path; const payload = {}; - if (data && typeof data === 'object') { + if (data && typeof data === "object") { for (const k in data) { payload[k] = data[k]; } @@ -238,72 +268,81 @@ const RESTController = { payload._context = context; } - if (method !== 'POST') { + if (method !== "POST") { payload._method = method; - method = 'POST'; + method = "POST"; } - payload._ApplicationId = CoreManager.get('APPLICATION_ID'); - const jsKey = CoreManager.get('JAVASCRIPT_KEY'); + payload._ApplicationId = CoreManager.get("APPLICATION_ID"); + const jsKey = CoreManager.get("JAVASCRIPT_KEY"); if (jsKey) { payload._JavaScriptKey = jsKey; } - payload._ClientVersion = CoreManager.get('VERSION'); + payload._ClientVersion = CoreManager.get("VERSION"); let useMasterKey = options.useMasterKey; - if (typeof useMasterKey === 'undefined') { - useMasterKey = CoreManager.get('USE_MASTER_KEY'); + if (typeof useMasterKey === "undefined") { + useMasterKey = CoreManager.get("USE_MASTER_KEY"); } if (useMasterKey) { - if (CoreManager.get('MASTER_KEY')) { + if (CoreManager.get("MASTER_KEY")) { delete payload._JavaScriptKey; - payload._MasterKey = CoreManager.get('MASTER_KEY'); + payload._MasterKey = CoreManager.get("MASTER_KEY"); } else { - throw new Error('Cannot use the Master Key, it has not been provided.'); + throw new Error("Cannot use the Master Key, it has not been provided."); } } - if (CoreManager.get('FORCE_REVOCABLE_SESSION')) { - payload._RevocableSession = '1'; + if (CoreManager.get("FORCE_REVOCABLE_SESSION")) { + payload._RevocableSession = "1"; } const installationId = options.installationId; let installationIdPromise; - if (installationId && typeof installationId === 'string') { + if (installationId && typeof installationId === "string") { installationIdPromise = Promise.resolve(installationId); } else { const installationController = CoreManager.getInstallationController(); 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 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 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; - } - }); - }).catch(RESTController.handleError); + }) + .catch(RESTController.handleError); }, handleError(response) { @@ -318,7 +357,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: ' + + "Received an error with invalid JSON from Parse: " + response.responseText ); } @@ -326,7 +365,7 @@ const RESTController = { const message = response.message ? response.message : response; error = new ParseError( ParseError.CONNECTION_FAILED, - 'XMLHttpRequest failed: ' + JSON.stringify(message) + "XMLHttpRequest failed: " + JSON.stringify(message) ); } return Promise.reject(error); @@ -338,7 +377,7 @@ const RESTController = { _getXHR() { return XHR; - } -} + }, +}; module.exports = RESTController; diff --git a/src/SingleInstanceStateController.js b/src/SingleInstanceStateController.js index 112cd74f4..569d38993 100644 --- a/src/SingleInstanceStateController.js +++ b/src/SingleInstanceStateController.js @@ -9,20 +9,25 @@ * @flow */ -import * as ObjectStateMutations from './ObjectStateMutations'; +import * as ObjectStateMutations from "./ObjectStateMutations"; -import type { Op } from './ParseOp'; -import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; +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,21 +114,42 @@ 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 { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttributes(serverData, pendingOps, obj.className, obj.id); -} - -export function commitServerChanges(obj: ObjectIdentifier, changes: AttributeMap) { + return ObjectStateMutations.estimateAttributes( + serverData, + pendingOps, + obj.className, + obj.id + ); +} + +export function commitServerChanges( + obj: ObjectIdentifier, + changes: AttributeMap +) { const state = initializeState(obj); - ObjectStateMutations.commitServerChanges(state.serverData, state.objectCache, changes); + ObjectStateMutations.commitServerChanges( + state.serverData, + state.objectCache, + changes + ); } -export function enqueueTask(obj: ObjectIdentifier, task: () => Promise): Promise { +export function enqueueTask( + obj: ObjectIdentifier, + task: () => Promise +): Promise { const state = initializeState(obj); return state.tasks.enqueue(task); } @@ -132,6 +158,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..9336bbd53 100644 --- a/src/Socket.weapp.js +++ b/src/Socket.weapp.js @@ -1,13 +1,13 @@ 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) => { this.onmessage(msg); @@ -33,4 +33,4 @@ module.exports = class SocketWeapp { close() { wx.closeSocket(); } -} +}; diff --git a/src/Storage.js b/src/Storage.js index 0388ca698..05c3553a9 100644 --- a/src/Storage.js +++ b/src/Storage.js @@ -9,7 +9,7 @@ * @flow */ -import CoreManager from './CoreManager'; +import CoreManager from "./CoreManager"; const Storage = { async(): boolean { @@ -21,7 +21,7 @@ const Storage = { const controller = CoreManager.getStorageController(); if (controller.async === 1) { throw new Error( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); } return controller.getItem(path); @@ -39,7 +39,7 @@ const Storage = { const controller = CoreManager.getStorageController(); if (controller.async === 1) { throw new Error( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); } return controller.setItem(path, value); @@ -57,7 +57,7 @@ const Storage = { const controller = CoreManager.getStorageController(); if (controller.async === 1) { throw new Error( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); } return controller.removeItem(path); @@ -75,7 +75,7 @@ const Storage = { const controller = CoreManager.getStorageController(); if (controller.async === 1) { throw new Error( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); } return controller.getAllKeys(); @@ -90,34 +90,34 @@ const Storage = { }, generatePath(path: string): string { - if (!CoreManager.get('APPLICATION_ID')) { - throw new Error('You need to call Parse.initialize before using Parse.'); + if (!CoreManager.get("APPLICATION_ID")) { + throw new Error("You need to call Parse.initialize before using Parse."); } - if (typeof path !== 'string') { - throw new Error('Tried to get a Storage path that was not a String.'); + if (typeof path !== "string") { + throw new Error("Tried to get a Storage path that was not a String."); } - if (path[0] === '/') { + if (path[0] === "/") { path = path.substr(1); } - return 'Parse/' + CoreManager.get('APPLICATION_ID') + '/' + path; + return "Parse/" + CoreManager.get("APPLICATION_ID") + "/" + path; }, _clear() { const controller = CoreManager.getStorageController(); - if (controller.hasOwnProperty('clear')) { + if (controller.hasOwnProperty("clear")) { controller.clear(); } - } + }, }; module.exports = Storage; -if (process.env.PARSE_BUILD === 'react-native') { - CoreManager.setStorageController(require('./StorageController.react-native')); -} else if (process.env.PARSE_BUILD === 'browser') { - CoreManager.setStorageController(require('./StorageController.browser')); -} else if (process.env.PARSE_BUILD === 'weapp') { - CoreManager.setStorageController(require('./StorageController.weapp')); +if (process.env.PARSE_BUILD === "react-native") { + CoreManager.setStorageController(require("./StorageController.react-native")); +} else if (process.env.PARSE_BUILD === "browser") { + CoreManager.setStorageController(require("./StorageController.browser")); +} else if (process.env.PARSE_BUILD === "weapp") { + CoreManager.setStorageController(require("./StorageController.weapp")); } else { - CoreManager.setStorageController(require('./StorageController.default')); + CoreManager.setStorageController(require("./StorageController.default")); } 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..51dd29588 100644 --- a/src/StorageController.react-native.js +++ b/src/StorageController.react-native.js @@ -10,7 +10,7 @@ * @private */ -import CoreManager from './CoreManager'; +import CoreManager from "./CoreManager"; const StorageController = { async: 1, @@ -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..5020c5488 100644 --- a/src/TaskQueue.js +++ b/src/TaskQueue.js @@ -8,11 +8,11 @@ * * @flow */ -import { resolvingPromise } from './promiseUtils'; +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..93cf6676d 100644 --- a/src/UniqueInstanceStateController.js +++ b/src/UniqueInstanceStateController.js @@ -9,12 +9,17 @@ * @flow */ -import * as ObjectStateMutations from './ObjectStateMutations'; -import TaskQueue from './TaskQueue'; - -import type { Op } from './ParseOp'; -import type ParseObject from './ParseObject'; -import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; +import * as ObjectStateMutations from "./ObjectStateMutations"; +import TaskQueue from "./TaskQueue"; + +import type { Op } from "./ParseOp"; +import type ParseObject from "./ParseObject"; +import type { + AttributeMap, + ObjectCache, + OpsMap, + State, +} from "./ObjectStateMutations"; let objectState = new WeakMap(); @@ -34,7 +39,7 @@ export function initializeState(obj: ParseObject, initial?: State): State { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }; } state = initial; @@ -103,18 +108,33 @@ 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 { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttributes(serverData, pendingOps, obj.className, obj.id); + return ObjectStateMutations.estimateAttributes( + serverData, + pendingOps, + obj.className, + obj.id + ); } export function commitServerChanges(obj: ParseObject, changes: AttributeMap) { const state = initializeState(obj); - ObjectStateMutations.commitServerChanges(state.serverData, state.objectCache, changes); + ObjectStateMutations.commitServerChanges( + state.serverData, + state.objectCache, + changes + ); } export function enqueueTask(obj: ParseObject, task: () => Promise): Promise { diff --git a/src/Xhr.weapp.js b/src/Xhr.weapp.js index ec6c20495..d706ca0f6 100644 --- a/src/Xhr.weapp.js +++ b/src/Xhr.weapp.js @@ -9,12 +9,12 @@ module.exports = class XhrWeapp { this.header = {}; this.readyState = this.DONE; this.status = 0; - this.response = ''; - this.responseType = ''; - this.responseText = ''; + this.response = ""; + this.responseType = ""; + this.responseText = ""; this.responseHeader = {}; - this.method = ''; - this.url = ''; + this.method = ""; + this.url = ""; this.onabort = () => {}; this.onprogress = () => {}; this.onerror = () => {}; @@ -23,9 +23,9 @@ module.exports = class XhrWeapp { } getAllResponseHeaders() { - let header = ''; - for(const key in this.responseHeader){ - header += key + ':' + this.getResponseHeader(key) + '\r\n' + let header = ""; + for (const key in this.responseHeader) { + header += key + ":" + this.getResponseHeader(key) + "\r\n"; } return header; } @@ -72,11 +72,11 @@ module.exports = class XhrWeapp { fail: (err) => { this.requestTask = null; this.onerror(err); - } + }, }); 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..56142a91b 100644 --- a/src/__tests__/Analytics-test.js +++ b/src/__tests__/Analytics-test.js @@ -7,78 +7,91 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../Analytics'); -jest.dontMock('../CoreManager'); +jest.dontMock("../Analytics"); +jest.dontMock("../CoreManager"); -const Analytics = require('../Analytics'); -const CoreManager = require('../CoreManager'); +const Analytics = require("../Analytics"); +const CoreManager = require("../CoreManager"); const defaultController = CoreManager.getAnalyticsController(); -describe('Analytics', () => { +describe("Analytics", () => { beforeEach(() => { const track = jest.fn(); track.mockReturnValue(Promise.resolve()); CoreManager.setAnalyticsController({ track: track }); }); - it('throws when no event name is provided', () => { - expect(Analytics.track) - .toThrow('A name for the custom event must be provided'); + it("throws when no event name is 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', {}]); + it("trims whitespace from event names", () => { + Analytics.track(" before", {}); + expect(CoreManager.getAnalyticsController().track.mock.calls[0]).toEqual([ + "before", + {}, + ]); - Analytics.track('after ', {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[1]) - .toEqual(['after', {}]); + Analytics.track("after ", {}); + expect(CoreManager.getAnalyticsController().track.mock.calls[1]).toEqual([ + "after", + {}, + ]); - Analytics.track(' both ', {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[2]) - .toEqual(['both', {}]); + Analytics.track(" 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' }]); + it("passes along event names and dimensions", () => { + Analytics.track("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".'); + 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', { '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".' + ); }); }); -describe('AnalyticsController', () => { +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 }); }); - it('passes dimensions along to the appropriate endpoint', () => { - Analytics.track('click', { x: '12', y: '40' }); + 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..7869bc64f 100644 --- a/src/__tests__/AnonymousUtils-test.js +++ b/src/__tests__/AnonymousUtils-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../AnonymousUtils'); +jest.dontMock("../AnonymousUtils"); class MockUser { - constructor () { - this.className = '_User'; + constructor() { + this.className = "_User"; this.attributes = {}; } _isLinked() {} @@ -20,7 +20,7 @@ class MockUser { static logInWith() {} } -jest.setMock('../ParseUser', MockUser); +jest.setMock("../ParseUser", MockUser); const mockProvider = { restoreAuthentication() { @@ -28,61 +28,67 @@ const mockProvider = { }, getAuthType() { - return 'anonymous'; + return "anonymous"; }, getAuthData() { return { authData: { - id: '1234', + id: "1234", }, }; }, }; -const AnonymousUtils = require('../AnonymousUtils').default; +const AnonymousUtils = require("../AnonymousUtils").default; -describe('AnonymousUtils', () => { +describe("AnonymousUtils", () => { beforeEach(() => { jest.clearAllMocks(); - jest.spyOn( - AnonymousUtils, - '_getAuthProvider' - ) + jest + .spyOn(AnonymousUtils, "_getAuthProvider") .mockImplementation(() => mockProvider); }); - it('can register provider', () => { + it("can register provider", () => { AnonymousUtils._getAuthProvider.mockRestore(); - jest.spyOn(MockUser, '_registerAuthenticationProvider'); + jest.spyOn(MockUser, "_registerAuthenticationProvider"); AnonymousUtils._getAuthProvider(); AnonymousUtils._getAuthProvider(); expect(MockUser._registerAuthenticationProvider).toHaveBeenCalledTimes(1); }); - it('can check user isLinked', () => { + it("can check user isLinked", () => { const user = new MockUser(); - jest.spyOn(user, '_isLinked'); + jest.spyOn(user, "_isLinked"); AnonymousUtils.isLinked(user); expect(user._isLinked).toHaveBeenCalledTimes(1); - expect(user._isLinked).toHaveBeenCalledWith('anonymous'); + expect(user._isLinked).toHaveBeenCalledWith("anonymous"); expect(AnonymousUtils._getAuthProvider).toHaveBeenCalledTimes(1); }); - it('can link user', () => { + it("can link user", () => { const user = new MockUser(); - jest.spyOn(user, 'linkWith'); + jest.spyOn(user, "linkWith"); AnonymousUtils.link(user); expect(user.linkWith).toHaveBeenCalledTimes(1); - expect(user.linkWith).toHaveBeenCalledWith('anonymous', mockProvider.getAuthData(), undefined); + expect(user.linkWith).toHaveBeenCalledWith( + "anonymous", + mockProvider.getAuthData(), + undefined + ); expect(AnonymousUtils._getAuthProvider).toHaveBeenCalledTimes(1); }); - it('can login user', () => { - jest.spyOn(MockUser, 'logInWith'); + it("can login user", () => { + 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..9691b4ae3 100644 --- a/src/__tests__/Cloud-test.js +++ b/src/__tests__/Cloud-test.js @@ -7,209 +7,286 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../Cloud'); -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseQuery'); +jest.dontMock("../Cloud"); +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseQuery"); -const Cloud = require('../Cloud'); -const CoreManager = require('../CoreManager'); +const Cloud = require("../Cloud"); +const CoreManager = require("../CoreManager"); const defaultController = CoreManager.getCloudController(); -describe('Cloud', () => { +describe("Cloud", () => { beforeEach(() => { 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.'); + it("run throws with an invalid function name", () => { + 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', {}); + 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', {}, {}]); - - Cloud.run('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' }]); - - Cloud.run('myfunction', {}, { useMasterKey: true, sessionToken: 'asdf1234' }); - - expect(CoreManager.getCloudController().run.mock.calls[3]) - .toEqual(['myfunction', {}, { useMasterKey: true, sessionToken: 'asdf1234' }]); + it("run passes options", () => { + Cloud.run("myfunction", {}, { useMasterKey: false }); + + 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 }, + ]); + + Cloud.run("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" }, + ]); }); - it('startJob throws with an invalid job name', () => { - expect(Cloud.startJob) - .toThrow('Cloud job name must be a string.'); + it("startJob throws with an invalid job name", () => { + 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', {}); + 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 }); + 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', () => { + 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 }, + ]); }); }); -describe('CloudController', () => { +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)) }); + it("run passes encoded requests", () => { + 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 }); + 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' }); + 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)); const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); - Cloud.run('myfunction').then(() => { + Cloud.run("myfunction").then(() => { done(); }); }); - it('startJob passes encoded requests', () => { - Cloud.startJob('myJob', { value: 12, when: new Date(Date.UTC(2015,0,1)) }); + it("startJob passes encoded requests", () => { + 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 }); + 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', () => { + 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', () => { + 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 () => { + it("accepts context on cloud function call", async () => { const request = jest.fn(); request.mockReturnValue(Promise.resolve(undefined)); @@ -218,29 +295,31 @@ describe('CloudController', () => { // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, 'request'); + jest.spyOn(controller, "request"); // Save object - const context = {a: "a"}; - await Cloud.run('myfunction', {}, { context: context }); + const context = { a: "a" }; + await Cloud.run("myfunction", {}, { context: context }); // Validate expect(controller.request.mock.calls[0][3].context).toEqual(context); }); - it('can get job status', async () => { + 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]; - expect(method).toBe('GET'); - expect(path).toBe('classes/_JobStatus'); + await Cloud.getJobStatus("jobId1234"); + const [method, path, data, options] = request.mock.calls[0]; + expect(method).toBe("GET"); + expect(path).toBe("classes/_JobStatus"); expect(data).toEqual({ limit: 1, where: { - objectId: 'jobId1234', + objectId: "jobId1234", }, }); expect(options.useMasterKey).toBe(true); diff --git a/src/__tests__/CoreManager-test.js b/src/__tests__/CoreManager-test.js index 81bb2691a..7d1e77dca 100644 --- a/src/__tests__/CoreManager-test.js +++ b/src/__tests__/CoreManager-test.js @@ -7,392 +7,436 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); +jest.dontMock("../CoreManager"); -const CoreManager = require('../CoreManager'); +const CoreManager = require("../CoreManager"); -describe('CoreManager', () => { - it('is initialized with default values', () => { - expect(CoreManager.get('SERVER_URL')).toBe('https://api.parse.com/1'); +describe("CoreManager", () => { + it("is initialized with default values", () => { + expect(CoreManager.get("SERVER_URL")).toBe("https://api.parse.com/1"); }); - it('pulls the version string from package.json', () => { - expect(CoreManager.get('VERSION').length).toBeGreaterThan(0); + it("pulls the version string from package.json", () => { + expect(CoreManager.get("VERSION").length).toBeGreaterThan(0); }); - it('detects when running in node', () => { - expect(CoreManager.get('IS_NODE')).toBe(true); + it("detects when running in node", () => { + expect(CoreManager.get("IS_NODE")).toBe(true); }); - it('can set and retrieve arbitrary values', () => { - expect(CoreManager.get.bind(null, 'something')).toThrow( - 'Configuration key not found: something' + it("can set and retrieve arbitrary values", () => { + expect(CoreManager.get.bind(null, "something")).toThrow( + "Configuration key not found: something" ); - CoreManager.set('something', 'a string'); - expect(CoreManager.get('something')).toBe('a string'); + CoreManager.set("something", "a string"); + expect(CoreManager.get("something")).toBe("a string"); }); - it('requires AnalyticsController to implement certain functionality', () => { + it("requires AnalyticsController to implement certain functionality", () => { expect(CoreManager.setAnalyticsController.bind(null, {})).toThrow( - 'AnalyticsController must implement track()' + "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', () => { + it("can set and get AnalyticsController", () => { const controller = { - track: function() {} + track: function () {}, }; CoreManager.setAnalyticsController(controller); expect(CoreManager.getAnalyticsController()).toBe(controller); }); - it('requires CloudController to implement certain functionality', () => { + it("requires CloudController to implement certain functionality", () => { expect(CoreManager.setCloudController.bind(null, {})).toThrow( - 'CloudController must implement run()' + "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', () => { + 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); expect(CoreManager.getCloudController()).toBe(controller); }); - it('requires ConfigController to implement certain functionality', () => { + it("requires ConfigController to implement certain functionality", () => { expect(CoreManager.setConfigController.bind(null, {})).toThrow( - 'ConfigController must implement current()' + "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', () => { + it("can set and get ConfigController", () => { const controller = { - current: function() {}, - get: function() {}, - save : function() {} + current: function () {}, + get: function () {}, + save: function () {}, }; CoreManager.setConfigController(controller); expect(CoreManager.getConfigController()).toBe(controller); }); - it('requires FileController to implement certain functionality', () => { + it("requires FileController to implement certain functionality", () => { expect(CoreManager.setFileController.bind(null, {})).toThrow( - 'FileController must implement saveFile()' + "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', () => { + it("can set and get FileController", () => { const controller = { - saveFile: function() {}, - saveBase64: function() {} + saveFile: function () {}, + saveBase64: function () {}, }; CoreManager.setFileController(controller); expect(CoreManager.getFileController()).toBe(controller); }); - it('requires InstallationController to implement certain functionality', () => { + it("requires InstallationController to implement certain functionality", () => { expect(CoreManager.setInstallationController.bind(null, {})).toThrow( - 'InstallationController must implement currentInstallationId()' + "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', () => { + it("can set and get InstallationController", () => { const controller = { - currentInstallationId: function() {} + currentInstallationId: function () {}, }; CoreManager.setInstallationController(controller); expect(CoreManager.getInstallationController()).toBe(controller); }); - it('requires PushController to implement certain functionality', () => { + it("requires PushController to implement certain functionality", () => { expect(CoreManager.setPushController.bind(null, {})).toThrow( - 'PushController must implement send()' + "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', () => { + it("can set and get PushController", () => { const controller = { - send: function() {} + send: function () {}, }; CoreManager.setPushController(controller); expect(CoreManager.getPushController()).toBe(controller); }); - it('requires ObjectController to implement certain functionality', () => { + it("requires ObjectController to implement certain functionality", () => { expect(CoreManager.setObjectController.bind(null, {})).toThrow( - 'ObjectController must implement save()' + "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', () => { + it("can set and get ObjectController", () => { const controller = { - save: function() {}, - fetch: function() {}, - destroy: function() {} + save: function () {}, + fetch: function () {}, + destroy: function () {}, }; CoreManager.setObjectController(controller); expect(CoreManager.getObjectController()).toBe(controller); }); - it('can set and get ObjectStateController', () => { + 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); expect(CoreManager.getObjectStateController()).toBe(controller); }); - it('requires QueryController to implement certain functionality', () => { + it("requires QueryController to implement certain functionality", () => { expect(CoreManager.setQueryController.bind(null, {})).toThrow( - 'QueryController must implement find()' + "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', () => { + it("can set and get QueryController", () => { const controller = { - find: function() {}, - aggregate: function() {} + find: function () {}, + aggregate: function () {}, }; CoreManager.setQueryController(controller); expect(CoreManager.getQueryController()).toBe(controller); }); - it('requires RESTController to implement certain functionality', () => { + it("requires RESTController to implement certain functionality", () => { expect(CoreManager.setRESTController.bind(null, {})).toThrow( - 'RESTController must implement request()' + "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', () => { + it("can set and get RESTController", () => { const controller = { - request: function() {}, - ajax: function() {} + request: function () {}, + ajax: function () {}, }; CoreManager.setRESTController(controller); expect(CoreManager.getRESTController()).toBe(controller); }); - it('requires StorageController to implement certain functionality', () => { + it("requires StorageController to implement certain functionality", () => { expect(CoreManager.setStorageController.bind(null, { async: 0 })).toThrow( - 'A synchronous StorageController must implement getItem()' + "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()' + "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', () => { + 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); expect(CoreManager.getStorageController()).toBe(controller); }); - it('requires SchemaController to implement certain functionality', () => { + it("requires SchemaController to implement certain functionality", () => { expect(CoreManager.setSchemaController.bind(null, {})).toThrow( - 'SchemaController must implement get()' + "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', () => { + 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); expect(CoreManager.getSchemaController()).toBe(controller); }); - it('requires LocalDatastoreController to implement certain functionality', () => { + it("requires LocalDatastoreController to implement certain functionality", () => { expect(CoreManager.setLocalDatastoreController.bind(null, {})).toThrow( - 'LocalDatastoreController must implement pinWithName()' + "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', () => { + 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); expect(CoreManager.getLocalDatastoreController()).toBe(controller); }); - it('can set and get WebSocketController', () => { + 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..b0b8d4043 100644 --- a/src/__tests__/FacebookUtils-test.js +++ b/src/__tests__/FacebookUtils-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../FacebookUtils'); +jest.dontMock("../FacebookUtils"); class MockUser { - constructor () { - this.className = '_User'; + constructor() { + this.className = "_User"; this.attributes = {}; } _isLinked() {} @@ -21,17 +21,17 @@ class MockUser { static logInWith() {} } -jest.setMock('../ParseUser', MockUser); +jest.setMock("../ParseUser", MockUser); -const FacebookUtils = require('../FacebookUtils').default; +const FacebookUtils = require("../FacebookUtils").default; -describe('FacebookUtils', () => { +describe("FacebookUtils", () => { beforeEach(() => { jest.clearAllMocks(); const authResponse = { - userID: 'test', - accessToken: 'test', - expiresIn: 'test', // Should be unix timestamp + userID: "test", + accessToken: "test", + expiresIn: "test", // Should be unix timestamp }; global.FB = { init: () => {}, @@ -42,215 +42,237 @@ describe('FacebookUtils', () => { }; }); - it('can not init without FB SDK', () => { + it("can not init without FB SDK", () => { global.FB = undefined; try { FacebookUtils.init(); } catch (e) { - expect(e.message).toBe('The Facebook JavaScript SDK must be loaded before calling init.'); + expect(e.message).toBe( + "The Facebook JavaScript SDK must be loaded before calling init." + ); } }); - it('can not login without init', async () => { + it("can not login without init", async () => { try { await FacebookUtils.logIn(); } catch (e) { - expect(e.message).toBe('You must initialize FacebookUtils before calling logIn.'); + expect(e.message).toBe( + "You must initialize FacebookUtils before calling logIn." + ); } }); - it('can not link without init', async () => { + it("can not link without init", async () => { try { const user = new MockUser(); await FacebookUtils.link(user); } catch (e) { - expect(e.message).toBe('You must initialize FacebookUtils before calling link.'); + expect(e.message).toBe( + "You must initialize FacebookUtils before calling link." + ); } }); - it('can not unlink without init', () => { + it("can not unlink without init", () => { try { const user = new MockUser(); FacebookUtils.unlink(user); } catch (e) { - expect(e.message).toBe('You must initialize FacebookUtils before calling unlink.'); + expect(e.message).toBe( + "You must initialize FacebookUtils before calling unlink." + ); } }); - it('can init', () => { + it("can init", () => { FacebookUtils.init(); }); - it('can init with options', () => { - jest.spyOn(console, 'warn') - .mockImplementationOnce(() => { - return { - call: () => {} - } - }) + it("can init with options", () => { + jest.spyOn(console, "warn").mockImplementationOnce(() => { + return { + call: () => {}, + }; + }); FacebookUtils.init({ status: true }); expect(console.warn).toHaveBeenCalled(); }); - it('can link', async () => { + it("can link", async () => { FacebookUtils.init(); const user = new MockUser(); await FacebookUtils.link(user); }); - it('can link with permission string', async () => { + it("can link with permission string", async () => { FacebookUtils.init(); const user = new MockUser(); - await FacebookUtils.link(user, 'public_profile'); + await FacebookUtils.link(user, "public_profile"); }); - it('can link with authData object', async () => { + it("can link with authData object", async () => { FacebookUtils.init(); const user = new MockUser(); const authData = { - id: '1234' + id: "1234", }; - jest.spyOn(user, 'linkWith'); + jest.spyOn(user, "linkWith"); await FacebookUtils.link(user, authData); - expect(user.linkWith).toHaveBeenCalledWith('facebook', { authData: { id: '1234' } }, undefined); + expect(user.linkWith).toHaveBeenCalledWith( + "facebook", + { authData: { id: "1234" } }, + undefined + ); }); - it('can link with options', async () => { + it("can link with options", async () => { FacebookUtils.init(); const user = new MockUser(); - jest.spyOn(user, 'linkWith'); + 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 () => { + it("can check isLinked", async () => { FacebookUtils.init(); const user = new MockUser(); - jest.spyOn(user, '_isLinked'); + jest.spyOn(user, "_isLinked"); await FacebookUtils.isLinked(user); - expect(user._isLinked).toHaveBeenCalledWith('facebook'); + expect(user._isLinked).toHaveBeenCalledWith("facebook"); }); - it('can unlink', async () => { + it("can unlink", async () => { FacebookUtils.init(); const user = new MockUser(); - const spy = jest.spyOn(user, '_unlinkFrom'); + const spy = jest.spyOn(user, "_unlinkFrom"); await FacebookUtils.unlink(user); expect(user._unlinkFrom).toHaveBeenCalledTimes(1); spy.mockRestore(); }); - it('can login', async () => { + it("can login", async () => { FacebookUtils.init(); await FacebookUtils.logIn(); }); - it('can login with permission string', async () => { + it("can login with permission string", async () => { FacebookUtils.init(); - jest.spyOn(MockUser, 'logInWith'); - await FacebookUtils.logIn('public_profile'); + jest.spyOn(MockUser, "logInWith"); + await FacebookUtils.logIn("public_profile"); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); }); - it('can login with authData', async () => { + it("can login with authData", async () => { FacebookUtils.init(); - jest.spyOn(MockUser, 'logInWith'); - await FacebookUtils.logIn({ id: '1234' }); + jest.spyOn(MockUser, "logInWith"); + await FacebookUtils.logIn({ id: "1234" }); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); }); - it('can login with options', async () => { + it("can login with options", async () => { FacebookUtils.init(); - jest.spyOn(MockUser, 'logInWith'); + 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 () => { + it("provider getAuthType", async () => { const provider = FacebookUtils._getAuthProvider(); - expect(provider.getAuthType()).toBe('facebook'); + expect(provider.getAuthType()).toBe("facebook"); }); - it('provider deauthenticate', async () => { + it("provider deauthenticate", async () => { const provider = FacebookUtils._getAuthProvider(); - jest.spyOn(provider, 'restoreAuthentication'); + jest.spyOn(provider, "restoreAuthentication"); provider.deauthenticate(); expect(provider.restoreAuthentication).toHaveBeenCalled(); }); }); -describe('FacebookUtils provider', () => { +describe("FacebookUtils provider", () => { beforeEach(() => { jest.clearAllMocks(); }); - it('restoreAuthentication', async () => { + it("restoreAuthentication", async () => { const provider = FacebookUtils._getAuthProvider(); const didRestore = provider.restoreAuthentication(); expect(didRestore).toBe(true); }); - it('restoreAuthentication with invalid authData', async () => { + it("restoreAuthentication with invalid authData", async () => { global.FB = { init: () => {}, logout: () => {}, getAuthResponse: () => { - return { userID: '5678' }; + return { userID: "5678" }; }, }; - jest.spyOn(global.FB, 'logout'); + jest.spyOn(global.FB, "logout"); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: '1234'}); + provider.restoreAuthentication({ id: "1234" }); expect(global.FB.logout).toHaveBeenCalled(); }); - it('restoreAuthentication with valid authData', async () => { + it("restoreAuthentication with valid authData", async () => { global.FB = { init: () => {}, getAuthResponse: () => { - return { userID: '1234' }; + return { userID: "1234" }; }, }; FacebookUtils.init({ status: false }); - jest.spyOn(global.FB, 'init'); + jest.spyOn(global.FB, "init"); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: '1234'}); + provider.restoreAuthentication({ id: "1234" }); expect(global.FB.init).toHaveBeenCalled(); }); - it('restoreAuthentication with valid authData', async () => { + it("restoreAuthentication with valid authData", async () => { global.FB = { init: () => {}, getAuthResponse: () => { - return { userID: '1234' }; + return { userID: "1234" }; }, }; FacebookUtils.init({ status: false }); - jest.spyOn(global.FB, 'init'); + 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 () => { + it("authenticate without FB error", async () => { global.FB = undefined; const options = { - error: () => {} + error: () => {}, }; - jest.spyOn(options, 'error'); + jest.spyOn(options, "error"); const provider = FacebookUtils._getAuthProvider(); try { provider.authenticate(options); } catch (e) { - expect(options.error).toHaveBeenCalledWith(provider, 'Facebook SDK not found.'); + expect(options.error).toHaveBeenCalledWith( + provider, + "Facebook SDK not found." + ); } }); - it('authenticate with FB response', async () => { + it("authenticate with FB response", async () => { const authResponse = { - userID: '1234', - accessToken: 'access_token', - expiresIn: '2000-01-01', + userID: "1234", + accessToken: "access_token", + expiresIn: "2000-01-01", }; global.FB = { init: () => {}, @@ -259,15 +281,19 @@ describe('FacebookUtils provider', () => { }, }; const options = { - success: () => {} + success: () => {}, }; - jest.spyOn(options, '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 () => { + it("authenticate with no FB response", async () => { global.FB = { init: () => {}, login: (cb) => { @@ -275,22 +301,22 @@ describe('FacebookUtils provider', () => { }, }; const options = { - error: () => {} + error: () => {}, }; - jest.spyOn(options, 'error'); + jest.spyOn(options, "error"); const provider = FacebookUtils._getAuthProvider(); provider.authenticate(options); expect(options.error).toHaveBeenCalledWith(provider, {}); }); - it('getAuthType', async () => { + it("getAuthType", async () => { const provider = FacebookUtils._getAuthProvider(); - expect(provider.getAuthType()).toBe('facebook'); + expect(provider.getAuthType()).toBe("facebook"); }); - it('deauthenticate', async () => { + it("deauthenticate", async () => { const provider = FacebookUtils._getAuthProvider(); - jest.spyOn(provider, 'restoreAuthentication'); + jest.spyOn(provider, "restoreAuthentication"); provider.deauthenticate(); expect(provider.restoreAuthentication).toHaveBeenCalled(); }); diff --git a/src/__tests__/Hooks-test.js b/src/__tests__/Hooks-test.js index a67f3dbd5..25b9a4aec 100644 --- a/src/__tests__/Hooks-test.js +++ b/src/__tests__/Hooks-test.js @@ -1,228 +1,280 @@ /** -* 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'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ParseError'); - -const Hooks = require('../ParseHooks'); -const CoreManager = require('../CoreManager'); + * 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"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ParseError"); + +const Hooks = require("../ParseHooks"); +const CoreManager = require("../CoreManager"); const defaultController = CoreManager.getHooksController(); const { sendRequest } = defaultController; -describe('Hooks', () => { +describe("Hooks", () => { beforeEach(() => { const run = jest.fn(); - run.mockReturnValue(Promise.resolve({ - result: {} - })); + run.mockReturnValue( + Promise.resolve({ + result: {}, + }) + ); defaultController.sendRequest = run; CoreManager.setHooksController(defaultController); }); - it('shoud properly build GET functions', () => { + 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', () => { + it("shoud properly build GET triggers", () => { Hooks.getTriggers(); - 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']); - }) - - it('shoud properly build GET trigger', () => { - Hooks.getTrigger('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', { - functionName: 'myFunction', - 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', { - className: 'MyClass', - triggerName: 'beforeSave', - 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' - }]); - }) - - 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' - }]); - }) - - - it('shoud properly build removeFunction', () => { - Hooks.removeFunction('myFunction'); - - 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([ + "GET", + "/hooks/triggers", + ]); + }); + + it("shoud properly build GET function", () => { + Hooks.getFunction("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", + ]); + }); + + it("shoud properly build POST function", () => { + Hooks.createFunction("myFunction", "https://dummy.com"); + + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + "POST", + "/hooks/functions", + { + functionName: "myFunction", + 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", + { + className: "MyClass", + triggerName: "beforeSave", + 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", + }, + ]); + }); + + 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", + }, + ]); + }); + + it("shoud properly build removeFunction", () => { + Hooks.removeFunction("myFunction"); + + 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"); + }); 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 () => { + it("should sendRequest", async () => { defaultController.sendRequest = sendRequest; - const request = function() { + const request = function () { return Promise.resolve(12); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); - const decoded = await defaultController.sendRequest('POST', 'hooks/triggers/myhook'); + const decoded = await defaultController.sendRequest( + "POST", + "hooks/triggers/myhook" + ); expect(decoded).toBe(12); }); - it('handle sendRequest error', async () => { + it("handle sendRequest error", async () => { defaultController.sendRequest = sendRequest; - const request = function() { + const request = function () { return Promise.resolve(undefined); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); try { - await defaultController.sendRequest('POST', 'hooks/triggers/myhook'); + await defaultController.sendRequest("POST", "hooks/triggers/myhook"); expect(false).toBe(true); } catch (e) { - expect(e.message).toBe('The server returned an invalid response.'); + expect(e.message).toBe("The server returned an invalid response."); } }); }); diff --git a/src/__tests__/InstallationController-test.js b/src/__tests__/InstallationController-test.js index 9a672208b..ed4ec76c4 100644 --- a/src/__tests__/InstallationController-test.js +++ b/src/__tests__/InstallationController-test.js @@ -7,61 +7,65 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../InstallationController'); -jest.dontMock('../Storage'); -jest.dontMock('../StorageController.default'); -jest.mock('uuid/v4', () => { +jest.dontMock("../CoreManager"); +jest.dontMock("../InstallationController"); +jest.dontMock("../Storage"); +jest.dontMock("../StorageController.default"); +jest.mock("uuid/v4", () => { let value = 0; - return () => value++ + ''; + return () => value++ + ""; }); -const CoreManager = require('../CoreManager'); -const InstallationController = require('../InstallationController'); -const Storage = require('../Storage'); +const CoreManager = require("../CoreManager"); +const InstallationController = require("../InstallationController"); +const Storage = require("../Storage"); -describe('InstallationController', () => { +describe("InstallationController", () => { beforeEach(() => { - CoreManager.set('APPLICATION_ID', 'A'); - CoreManager.set('JAVASCRIPT_KEY', 'B'); + CoreManager.set("APPLICATION_ID", "A"); + CoreManager.set("JAVASCRIPT_KEY", "B"); Storage._clear(); InstallationController._clearCache(); }); - it('generates a new installation id when there is none', (done) => { + it("generates a new installation id when there is none", (done) => { InstallationController.currentInstallationId().then((iid) => { - expect(typeof iid).toBe('string'); + 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) => { - const iid = '12345678'; + it("can set installation id", (done) => { + const iid = "12345678"; InstallationController._setInstallationIdCache(iid); InstallationController.currentInstallationId().then((i) => { expect(i).toBe(iid); diff --git a/src/__tests__/LiveQueryClient-test.js b/src/__tests__/LiveQueryClient-test.js index ae52d92bd..e690dc137 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -7,33 +7,33 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../LiveQueryClient'); -jest.dontMock('../arrayContainsObject'); -jest.dontMock('../canBeSerialized'); -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../equals'); -jest.dontMock('../escape'); -jest.dontMock('../promiseUtils'); -jest.dontMock('../EventEmitter'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../parseDate'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../RESTController'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../TaskQueue'); -jest.dontMock('../unique'); -jest.dontMock('../UniqueInstanceStateController'); -jest.dontMock('../unsavedChildren'); -jest.dontMock('../ParseACL'); -jest.dontMock('../ParseQuery'); -jest.dontMock('../LiveQuerySubscription'); -jest.dontMock('../LocalDatastore'); +jest.dontMock("../LiveQueryClient"); +jest.dontMock("../arrayContainsObject"); +jest.dontMock("../canBeSerialized"); +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../equals"); +jest.dontMock("../escape"); +jest.dontMock("../promiseUtils"); +jest.dontMock("../EventEmitter"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../parseDate"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../RESTController"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../TaskQueue"); +jest.dontMock("../unique"); +jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock("../unsavedChildren"); +jest.dontMock("../ParseACL"); +jest.dontMock("../ParseQuery"); +jest.dontMock("../LiveQuerySubscription"); +jest.dontMock("../LocalDatastore"); jest.useFakeTimers(); @@ -41,60 +41,62 @@ const mockLocalDatastore = { isEnabled: false, _updateObjectIfPinned: jest.fn(), }; -jest.setMock('../LocalDatastore', mockLocalDatastore); +jest.setMock("../LocalDatastore", mockLocalDatastore); -const CoreManager = require('../CoreManager'); -const LiveQueryClient = require('../LiveQueryClient').default; -const ParseObject = require('../ParseObject').default; -const ParseQuery = require('../ParseQuery').default; -const { resolvingPromise } = require('../promiseUtils'); -const events = require('events'); +const CoreManager = require("../CoreManager"); +const LiveQueryClient = require("../LiveQueryClient").default; +const ParseObject = require("../ParseObject").default; +const ParseQuery = require("../ParseQuery").default; +const { resolvingPromise } = require("../promiseUtils"); +const events = require("events"); CoreManager.setLocalDatastore(mockLocalDatastore); -describe('LiveQueryClient', () => { +describe("LiveQueryClient", () => { beforeEach(() => { mockLocalDatastore.isEnabled = false; }); - it('serverURL required', () => { + it("serverURL required", () => { expect(() => { new LiveQueryClient({}); - }).toThrow('You need to set a proper Parse LiveQuery server url before using 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({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); - liveQueryClient.on('error', (error) => { - expect(error).toBe('Can not find WebSocket implementation'); + liveQueryClient.on("error", (error) => { + expect(error).toBe("Can not find WebSocket implementation"); CoreManager.setWebSocketController(WebSocketImplementation); done(); - }) + }); liveQueryClient.open(); }); - it('can unsubscribe', async () => { + it("can unsubscribe", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const subscription = { - id: 1 - } + id: 1, + }; liveQueryClient.subscriptions.set(1, subscription); liveQueryClient.unsubscribe(subscription); @@ -104,18 +106,18 @@ describe('LiveQueryClient', () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'unsubscribe', - requestId: 1 + op: "unsubscribe", + requestId: 1, }); }); - it('can handle open / close states', () => { + it("can handle open / close states", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); expect(liveQueryClient.shouldOpen()).toBe(true); liveQueryClient.close(); @@ -124,28 +126,28 @@ describe('LiveQueryClient', () => { expect(liveQueryClient.shouldOpen()).toBe(false); }); - it('set undefined sessionToken default', () => { + it("set undefined sessionToken default", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", }); expect(liveQueryClient.sessionToken).toBe(undefined); }); - it('can connect to server', () => { + it("can connect to server", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Mock _getWebSocketImplementation - liveQueryClient._getWebSocketImplementation = function() { + liveQueryClient._getWebSocketImplementation = function () { return jest.fn(); - } + }; // Mock handlers liveQueryClient._handleWebSocketOpen = jest.fn(); liveQueryClient._handleWebSocketMessage = jest.fn(); @@ -155,7 +157,7 @@ describe('LiveQueryClient', () => { liveQueryClient.open(); // Verify inner state - expect(liveQueryClient.state).toEqual('connecting'); + expect(liveQueryClient.state).toEqual("connecting"); // Verify handlers liveQueryClient.socket.onopen({}); expect(liveQueryClient._handleWebSocketOpen).toBeCalled(); @@ -167,16 +169,16 @@ describe('LiveQueryClient', () => { expect(liveQueryClient._handleWebSocketError).toBeCalled(); }); - it('can handle WebSocket open message', () => { + it("can handle WebSocket open message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; liveQueryClient._handleWebSocketOpen(); @@ -184,31 +186,31 @@ describe('LiveQueryClient', () => { expect(liveQueryClient.socket.send).toBeCalled(); const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); - expect(message.op).toEqual('connect'); - expect(message.applicationId).toEqual('applicationId'); - expect(message.javascriptKey).toEqual('javascriptKey'); - expect(message.masterKey).toEqual('masterKey'); - expect(message.sessionToken).toEqual('sessionToken'); + expect(message.op).toEqual("connect"); + expect(message.applicationId).toEqual("applicationId"); + expect(message.javascriptKey).toEqual("javascriptKey"); + expect(message.masterKey).toEqual("masterKey"); + expect(message.sessionToken).toEqual("sessionToken"); }); - it('can handle WebSocket connected response message', async () => { + it("can handle WebSocket connected response message", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); const data = { - op: 'connected', - clientId: 1 + op: "connected", + 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; }); @@ -217,47 +219,47 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); expect(liveQueryClient.id).toBe(1); await liveQueryClient.connectPromise; - expect(liveQueryClient.state).toEqual('connected'); + expect(liveQueryClient.state).toEqual("connected"); }); - it('can handle WebSocket reconnect on connected response message', async () => { + it("can handle WebSocket reconnect on connected response message", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); const data = { - op: 'connected', - clientId: 1 + op: "connected", + 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'); + jest.spyOn(liveQueryClient, "resubscribe"); liveQueryClient._handleReconnect(); liveQueryClient._handleWebSocketMessage(event); expect(isChecked).toBe(true); expect(liveQueryClient.id).toBe(1); await liveQueryClient.connectPromise; - expect(liveQueryClient.state).toEqual('connected'); + expect(liveQueryClient.state).toEqual("connected"); expect(liveQueryClient.resubscribe).toHaveBeenCalledTimes(1); }); - it('can handle WebSocket subscribed response message', () => { + it("can handle WebSocket subscribed response message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -265,16 +267,16 @@ describe('LiveQueryClient', () => { liveQueryClient.subscriptions.set(1, subscription); const data = { - op: 'subscribed', + 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; }); @@ -283,51 +285,51 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket unsubscribed response message', () => { + it("can handle WebSocket unsubscribed response message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); liveQueryClient.subscriptions.set(1, subscription); const data = { - op: 'unsubscribed', + 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); }); - it('can handle WebSocket error response message', () => { + it("can handle WebSocket error response message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); const data = { - op: 'error', + 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'); + expect(error).toEqual("error"); }); liveQueryClient._handleWebSocketMessage(event); @@ -335,32 +337,32 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket error while subscribing', () => { + it("can handle WebSocket error while subscribing", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); liveQueryClient.subscriptions.set(1, subscription); const data = { - op: 'error', + 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'); + expect(error).toEqual("error thrown"); }); liveQueryClient._handleWebSocketMessage(event); @@ -369,35 +371,35 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket event response message', () => { + it("can handle WebSocket event response message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject('Test'); - object.set('key', 'value'); + const object = new ParseObject("Test"); + object.set("key", "value"); const data = { - op: 'create', + 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(); - expect(parseObject.get('__type')).toBeUndefined(); + expect(parseObject.get("key")).toEqual("value"); + expect(parseObject.get("className")).toBeUndefined(); + expect(parseObject.get("__type")).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -405,64 +407,64 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket event response message without subscription', () => { + it("can handle WebSocket event response message without subscription", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); - const object = new ParseObject('Test'); - object.set('key', 'value'); + const object = new ParseObject("Test"); + object.set("key", "value"); const data = { - op: 'create', + 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); }); - it('can handle WebSocket response with original', () => { + it("can handle WebSocket response with original", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject('Test'); - const original = new ParseObject('Test'); - object.set('key', 'value'); - original.set('key', 'old'); + const object = new ParseObject("Test"); + const original = new ParseObject("Test"); + object.set("key", "value"); + original.set("key", "old"); const data = { - op: 'update', + op: "update", clientId: 1, requestId: 1, object: object._toFullJSON(), 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) => { + subscription.on("update", (parseObject, parseOriginalObject) => { isChecked = true; - expect(parseObject.get('key')).toEqual('value'); - expect(parseObject.get('className')).toBeUndefined(); - expect(parseObject.get('__type')).toBeUndefined(); + expect(parseObject.get("key")).toEqual("value"); + expect(parseObject.get("className")).toBeUndefined(); + expect(parseObject.get("__type")).toBeUndefined(); - expect(parseOriginalObject.get('key')).toEqual('old'); - expect(parseOriginalObject.get('className')).toBeUndefined(); - expect(parseOriginalObject.get('__type')).toBeUndefined(); + expect(parseOriginalObject.get("key")).toEqual("old"); + expect(parseOriginalObject.get("className")).toBeUndefined(); + expect(parseOriginalObject.get("__type")).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -470,50 +472,45 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket response override data on update', () => { + it("can handle WebSocket response override data on update", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject('Test'); - const original = new ParseObject('Test'); - object.set('key', 'value'); - original.set('key', 'old'); + const object = new ParseObject("Test"); + const original = new ParseObject("Test"); + object.set("key", "value"); + original.set("key", "old"); const data = { - op: 'update', + op: "update", clientId: 1, requestId: 1, object: object._toFullJSON(), 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; - subscription.on('update', () => { + subscription.on("update", () => { isChecked = true; }); @@ -527,35 +524,35 @@ describe('LiveQueryClient', () => { spy.mockRestore(); }); - it('can handle WebSocket response unset field', async () => { + it("can handle WebSocket response unset field", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject('Test'); - const original = new ParseObject('Test'); - const pointer = new ParseObject('PointerTest'); - pointer.id = '1234'; - original.set('pointer', pointer); + const object = new ParseObject("Test"); + const original = new ParseObject("Test"); + const pointer = new ParseObject("PointerTest"); + pointer.id = "1234"; + original.set("pointer", pointer); const data = { - op: 'update', + op: "update", clientId: 1, requestId: 1, object: object._toFullJSON(), original: original._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; let isChecked = false; - subscription.on('update', (parseObject, parseOriginalObject) => { + subscription.on("update", (parseObject, parseOriginalObject) => { isChecked = true; expect(parseObject.toJSON().pointer).toBeUndefined(); expect(parseOriginalObject.toJSON().pointer.objectId).toEqual(pointer.id); @@ -566,24 +563,24 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket close message', () => { + it("can handle WebSocket close message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + 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; }); @@ -593,24 +590,24 @@ describe('LiveQueryClient', () => { expect(isCheckedAgain).toBe(true); }); - it('can handle WebSocket close message while disconnected', () => { + it("can handle WebSocket close message while disconnected", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + 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(); @@ -621,20 +618,20 @@ describe('LiveQueryClient', () => { expect(isCheckedAgain).toBe(true); }); - it('can handle reconnect', () => { + it("can handle reconnect", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.open = jest.fn(); const attempts = liveQueryClient.attempts; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual('reconnecting'); + expect(liveQueryClient.state).toEqual("reconnecting"); jest.runOnlyPendingTimers(); @@ -642,25 +639,25 @@ describe('LiveQueryClient', () => { expect(liveQueryClient.open).toBeCalled(); }); - it('can handle reconnect and clear handler', () => { + it("can handle reconnect and clear handler", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.open = jest.fn(); const attempts = liveQueryClient.attempts; - liveQueryClient.state = 'disconnected'; + liveQueryClient.state = "disconnected"; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual('disconnected'); + expect(liveQueryClient.state).toEqual("disconnected"); - liveQueryClient.state = 'connected'; + liveQueryClient.state = "connected"; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual('reconnecting'); + expect(liveQueryClient.state).toEqual("reconnecting"); liveQueryClient._handleReconnect(); jest.runOnlyPendingTimers(); @@ -669,17 +666,17 @@ describe('LiveQueryClient', () => { expect(liveQueryClient.open).toBeCalled(); }); - it('can handle WebSocket error message', () => { + it("can handle WebSocket error message", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + 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 +686,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' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + 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(); }); @@ -708,30 +705,30 @@ describe('LiveQueryClient', () => { liveQueryClient._handleWebSocketError(error); }); - it('can handle WebSocket reconnect on error event', () => { + it("can handle WebSocket reconnect on error event", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); expect(liveQueryClient.additionalProperties).toBe(true); const data = { - op: 'error', + op: "error", code: 1, reconnect: true, - error: 'Additional properties not allowed', + 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); }); - const spy = jest.spyOn(liveQueryClient, '_handleReconnect'); + const spy = jest.spyOn(liveQueryClient, "_handleReconnect"); liveQueryClient._handleWebSocketMessage(event); expect(isChecked).toBe(true); @@ -740,19 +737,19 @@ describe('LiveQueryClient', () => { spy.mockRestore(); }); - it('can subscribe', async () => { + it("can subscribe", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; - const query = new ParseQuery('Test'); - query.equalTo('key', 'value'); + const query = new ParseQuery("Test"); + query.equalTo("key", "value"); const subscribePromise = liveQueryClient.subscribe(query); const clientSub = liveQueryClient.subscriptions.get(1); @@ -766,70 +763,70 @@ describe('LiveQueryClient', () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'subscribe', + op: "subscribe", requestId: 1, query: { - className: 'Test', + className: "Test", where: { - key: 'value' - } - } + key: "value", + }, + }, }); }); - it('can subscribe with sessionToken', async () => { + it("can subscribe with sessionToken", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; - const query = new ParseQuery('Test'); - query.equalTo('key', 'value'); + const query = new ParseQuery("Test"); + query.equalTo("key", "value"); - const subscribePromise = liveQueryClient.subscribe(query, 'mySessionToken'); + const subscribePromise = liveQueryClient.subscribe(query, "mySessionToken"); const clientSub = liveQueryClient.subscriptions.get(1); clientSub.subscribePromise.resolve(); const subscription = await subscribePromise; liveQueryClient.connectPromise.resolve(); expect(subscription).toBe(clientSub); - expect(subscription.sessionToken).toBe('mySessionToken'); + expect(subscription.sessionToken).toBe("mySessionToken"); expect(liveQueryClient.requestId).toBe(2); await liveQueryClient.connectPromise; const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'subscribe', + op: "subscribe", requestId: 1, - sessionToken: 'mySessionToken', + sessionToken: "mySessionToken", query: { - className: 'Test', + className: "Test", where: { - key: 'value' - } - } + key: "value", + }, + }, }); }); - it('can unsubscribe', async () => { + it("can unsubscribe", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const subscription = { - id: 1 - } + id: 1, + }; liveQueryClient.subscriptions.set(1, subscription); liveQueryClient.unsubscribe(subscription); @@ -839,21 +836,21 @@ describe('LiveQueryClient', () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'unsubscribe', - requestId: 1 + op: "unsubscribe", + requestId: 1, }); }); - it('can unsubscribe without subscription', async () => { + it("can unsubscribe without subscription", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; liveQueryClient.unsubscribe(); liveQueryClient.connectPromise.resolve(); @@ -861,19 +858,19 @@ describe('LiveQueryClient', () => { expect(liveQueryClient.socket.send).toHaveBeenCalledTimes(0); }); - it('can resubscribe', async () => { + it("can resubscribe", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; - const query = new ParseQuery('Test'); - query.equalTo('key', 'value'); + const query = new ParseQuery("Test"); + query.equalTo("key", "value"); liveQueryClient.subscribe(query); liveQueryClient.connectPromise.resolve(); @@ -884,31 +881,31 @@ describe('LiveQueryClient', () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'subscribe', + op: "subscribe", requestId: 1, query: { - className: 'Test', + className: "Test", where: { - key: 'value' - } - } + key: "value", + }, + }, }); }); - it('can resubscribe with sessionToken', async () => { + it("can resubscribe with sessionToken", async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; - const query = new ParseQuery('Test'); - query.equalTo('key', 'value'); - liveQueryClient.subscribe(query, 'mySessionToken'); + const query = new ParseQuery("Test"); + query.equalTo("key", "value"); + liveQueryClient.subscribe(query, "mySessionToken"); liveQueryClient.connectPromise.resolve(); liveQueryClient.resubscribe(); @@ -918,39 +915,39 @@ describe('LiveQueryClient', () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: 'subscribe', + op: "subscribe", requestId: 1, - sessionToken: 'mySessionToken', + sessionToken: "mySessionToken", query: { - className: 'Test', + className: "Test", where: { - key: 'value' - } - } + key: "value", + }, + }, }); }); - it('can close', () => { + it("can close", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); - liveQueryClient.state = 'connected'; + 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; }); @@ -960,42 +957,42 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); expect(isCheckedAgain).toBe(true); expect(liveQueryClient.socket.close).toBeCalled(); - expect(liveQueryClient.state).toBe('disconnected'); + expect(liveQueryClient.state).toBe("disconnected"); }); - it('can handle WebSocket subclass', () => { - const MyExtendedClass = ParseObject.extend('MyExtendedClass'); - ParseObject.registerSubclass('MyExtendedClass', MyExtendedClass); + it("can handle WebSocket subclass", () => { + const MyExtendedClass = ParseObject.extend("MyExtendedClass"); + ParseObject.registerSubclass("MyExtendedClass", MyExtendedClass); const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', - sessionToken: 'sessionToken' + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", + sessionToken: "sessionToken", }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); const object = new MyExtendedClass(); - object.set('key', 'value'); + object.set("key", "value"); const data = { - op: 'create', + op: "create", clientId: 1, requestId: 1, 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'); - expect(parseObject.get('className')).toBeUndefined(); - expect(parseObject.get('__type')).toBeUndefined(); + expect(parseObject.get("key")).toEqual("value"); + expect(parseObject.get("className")).toBeUndefined(); + expect(parseObject.get("__type")).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -1003,12 +1000,12 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('cannot subscribe without query', () => { + it("cannot subscribe without query", () => { const liveQueryClient = new LiveQueryClient({ - applicationId: 'applicationId', - serverURL: 'ws://test', - javascriptKey: 'javascriptKey', - masterKey: 'masterKey', + applicationId: "applicationId", + serverURL: "ws://test", + javascriptKey: "javascriptKey", + masterKey: "masterKey", }); const subscription = liveQueryClient.subscribe(); expect(subscription).toBe(undefined); diff --git a/src/__tests__/LocalDatastore-test.js b/src/__tests__/LocalDatastore-test.js index b0038459f..df888b90c 100644 --- a/src/__tests__/LocalDatastore-test.js +++ b/src/__tests__/LocalDatastore-test.js @@ -9,14 +9,14 @@ /* global window */ jest.autoMockOff(); -jest.unmock('../LocalDatastoreUtils'); +jest.unmock("../LocalDatastoreUtils"); -const encode = require('../encode').default; +const encode = require("../encode").default; let objectCount = 0; class MockObject { - constructor (className) { + constructor(className) { this.className = className; this.attributes = {}; @@ -32,15 +32,15 @@ class MockObject { } toPointer() { - return 'POINTER'; + return "POINTER"; } dirty() {} _toFullJSON() { const json = { - __type: 'Object', - className: this.className + __type: "Object", + className: this.className, }; for (const attr in this.attributes) { if (this.attributes[attr].id) { @@ -59,7 +59,7 @@ class MockObject { const o = new MockObject(json.className); o.id = json.objectId; for (const attr in json) { - if (attr !== 'className' && attr !== '__type' && attr !== 'objectId') { + if (attr !== "className" && attr !== "__type" && attr !== "objectId") { o.attributes[attr] = json[attr]; } } @@ -75,7 +75,7 @@ class MockObject { } } -const mockAsyncStorage = require('./test_helpers/mockRNStorage'); +const mockAsyncStorage = require("./test_helpers/mockRNStorage"); const mockLocalStorageController = { fromPinWithName: jest.fn(), pinWithName: jest.fn(), @@ -83,10 +83,10 @@ const mockLocalStorageController = { getAllContents: jest.fn(), clear: jest.fn(), }; -jest.setMock('../ParseObject', MockObject); +jest.setMock("../ParseObject", MockObject); const mockQueryFind = jest.fn(); -jest.mock('../ParseQuery', () => { +jest.mock("../ParseQuery", () => { return jest.fn().mockImplementation(function () { this.equalTo = jest.fn(); this.containedIn = jest.fn(); @@ -95,283 +95,297 @@ jest.mock('../ParseQuery', () => { }); }); -const CoreManager = require('../CoreManager'); -const LocalDatastore = require('../LocalDatastore'); -const ParseObject = require('../ParseObject'); -const ParseQuery = require('../ParseQuery'); -const ParseUser = require('../ParseUser').default; -const LocalDatastoreController = require('../LocalDatastoreController'); -const RNDatastoreController = require('../LocalDatastoreController.react-native'); -const BrowserStorageController = require('../StorageController.browser'); -const DefaultStorageController = require('../StorageController.default'); +const CoreManager = require("../CoreManager"); +const LocalDatastore = require("../LocalDatastore"); +const ParseObject = require("../ParseObject"); +const ParseQuery = require("../ParseQuery"); +const ParseUser = require("../ParseUser").default; +const LocalDatastoreController = require("../LocalDatastoreController"); +const RNDatastoreController = require("../LocalDatastoreController.react-native"); +const BrowserStorageController = require("../StorageController.browser"); +const DefaultStorageController = require("../StorageController.default"); -const item1 = new ParseObject('Item'); -const item2 = new ParseObject('Item'); -const item3 = new ParseObject('Item'); +const item1 = new ParseObject("Item"); +const item2 = new ParseObject("Item"); +const item3 = new ParseObject("Item"); -item1.id = '1'; -item2.id = '2'; -item3.id = '3'; +item1.id = "1"; +item2.id = "2"; +item3.id = "3"; 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', () => { +describe("LocalDatastore", () => { beforeEach(() => { CoreManager.setLocalDatastoreController(mockLocalStorageController); jest.clearAllMocks(); LocalDatastore.isEnabled = true; }); - it('isEnabled', () => { + it("isEnabled", () => { LocalDatastore.isEnabled = true; const isEnabled = LocalDatastore.checkIfEnabled(); expect(isEnabled).toBe(true); }); - it('isDisabled', () => { - const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + it("isDisabled", () => { + const spy = jest.spyOn(console, "error").mockImplementationOnce(() => {}); LocalDatastore.isEnabled = false; const isEnabled = LocalDatastore.checkIfEnabled(); expect(isEnabled).toBe(false); - LocalDatastore._updateLocalIdForObject('', null); + LocalDatastore._updateLocalIdForObject("", null); LocalDatastore._destroyObjectIfPinned(null); LocalDatastore._updateObjectIfPinned(null); - expect(spy).toHaveBeenCalledWith('Parse.enableLocalDatastore() must be called first'); + expect(spy).toHaveBeenCalledWith( + "Parse.enableLocalDatastore() must be called first" + ); spy.mockRestore(); }); - it('can clear', async () => { + it("can clear", async () => { await LocalDatastore._clear(); expect(mockLocalStorageController.clear).toHaveBeenCalledTimes(1); }); - it('can getAllContents', async () => { + it("can getAllContents", async () => { await LocalDatastore._getAllContents(); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it('_handlePinAllWithName no children', async () => { - const object = new ParseObject('Item'); - await LocalDatastore._handlePinAllWithName('test_pin', [object]); + it("_handlePinAllWithName no children", async () => { + const object = new ParseObject("Item"); + await LocalDatastore._handlePinAllWithName("test_pin", [object]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it('_handlePinAllWithName with localId', async () => { - const object = new ParseObject('Item'); - object._localId = 'local0'; + it("_handlePinAllWithName with localId", async () => { + const object = new ParseObject("Item"); + object._localId = "local0"; object.id = null; - await LocalDatastore._handlePinAllWithName('test_pin', [object]); - expect(mockLocalStorageController.pinWithName.mock.calls[0][0]).toEqual('Parse_LDS_Item_local0'); + await LocalDatastore._handlePinAllWithName("test_pin", [object]); + 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" }, ]); }); - it('_handlePinAllWithName default pin', async () => { - const object = new ParseObject('Item'); + it("_handlePinAllWithName default pin", async () => { + const object = new ParseObject("Item"); await LocalDatastore._handlePinAllWithName(DEFAULT_PIN, [object]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it('_handlePinAllWithName unsaved children', async () => { - const parent = new ParseObject('Item'); - const unsaved = { className: 'Item', __type: 'Object' }; - parent.set('child', unsaved); - await LocalDatastore._handlePinAllWithName('test_pin', [parent]); + it("_handlePinAllWithName unsaved children", async () => { + const parent = new ParseObject("Item"); + const unsaved = { className: "Item", __type: "Object" }; + parent.set("child", unsaved); + await LocalDatastore._handlePinAllWithName("test_pin", [parent]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it('_handlePinAllWithName with children', async () => { - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - const grandchild = new ParseObject('Item'); - child.set('grandchild', grandchild); - parent.set('child', child); - await LocalDatastore._handlePinAllWithName('test_pin', [parent]); + it("_handlePinAllWithName with children", async () => { + const parent = new ParseObject("Item"); + const child = new ParseObject("Item"); + const grandchild = new ParseObject("Item"); + child.set("grandchild", grandchild); + parent.set("child", child); + await LocalDatastore._handlePinAllWithName("test_pin", [parent]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(4); }); - it('_handleUnPinAllWithName default pin', async () => { + it("_handleUnPinAllWithName default pin", async () => { 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]); + expect( + mockLocalStorageController.pinWithName + ).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); }); - it('_handleUnPinAllWithName specific pin', async () => { + it("_handleUnPinAllWithName specific pin", async () => { const LDS = { parsePin_test_pin: [KEY1, KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); - await LocalDatastore._handleUnPinAllWithName('test_pin', [item1]); + 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 () => { - const object = new ParseObject('Item'); + it("_handleUnPinAllWithName default pin remove pinName", async () => { + const object = new ParseObject("Item"); 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); + expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( + DEFAULT_PIN + ); }); - it('_handleUnPinAllWithName specific pin remove pinName', async () => { - const object = new ParseObject('Item'); + it("_handleUnPinAllWithName specific pin remove pinName", async () => { + const object = new ParseObject("Item"); const LDS = { - [PIN_PREFIX + 'test_pin']: [], + [PIN_PREFIX + "test_pin"]: [], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); - await LocalDatastore._handleUnPinAllWithName('test_pin', [object]); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); + await LocalDatastore._handleUnPinAllWithName("test_pin", [object]); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(2); - expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin'); + expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( + PIN_PREFIX + "test_pin" + ); }); - it('_handleUnPinAllWithName remove if exist', async () => { + it("_handleUnPinAllWithName remove if exist", async () => { const objects = [KEY1, KEY2, KEY3]; const LDS = { - [PIN_PREFIX + 'test_pin']: objects, - [PIN_PREFIX + 'test_pin_2']: objects, + [PIN_PREFIX + "test_pin"]: objects, + [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]); + 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 () => { - const object = new ParseObject('Item'); + it("_updateObjectIfPinned not pinned", async () => { + const object = new ParseObject("Item"); LocalDatastore.isEnabled = true; LocalDatastore._updateObjectIfPinned(object); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it('_updateObjectIfPinned if pinned', async () => { - mockLocalStorageController - .fromPinWithName - .mockImplementationOnce(() => [item1]); + it("_updateObjectIfPinned if pinned", async () => { + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => [ + item1, + ]); LocalDatastore.isEnabled = true; await LocalDatastore._updateObjectIfPinned(item1); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual([item1]); + 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 () => { - await LocalDatastore._updateLocalIdForObject('local0', item1); - expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual(undefined); + it("_updateLocalIdForObject not pinned", async () => { + await LocalDatastore._updateLocalIdForObject("local0", item1); + expect( + mockLocalStorageController.fromPinWithName.mock.results[0].value + ).toEqual(undefined); }); - it('_updateLocalIdForObject if pinned', async () => { - const object = new ParseObject('Item'); + it("_updateLocalIdForObject if pinned", async () => { + const object = new ParseObject("Item"); const json = object._toFullJSON(); - const localId = 'local' + object.id; + const localId = "local" + object.id; const localKey = `${OBJECT_PREFIX}Item_${localId}`; const LDS = { [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); }); - it('_updateLocalIdForObject if pinned with name', async () => { - const object = new ParseObject('Item'); + it("_updateLocalIdForObject if pinned with name", async () => { + const object = new ParseObject("Item"); const json = object._toFullJSON(); - const localId = 'local' + object.id; + const localId = "local" + object.id; const localKey = `${OBJECT_PREFIX}Item_${localId}`; const LDS = { - [PIN_PREFIX + 'test_pin']: [localKey], + [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); }); - it('_updateLocalIdForObject if pinned with new name', async () => { - const object = new ParseObject('Item'); + it("_updateLocalIdForObject if pinned with new name", async () => { + const object = new ParseObject("Item"); const json = object._toFullJSON(); - const localId = 'local' + object.id; + const localId = "local" + object.id; const LDS = { [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); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual(json); + 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); }); - it('_serializeObjectsFromPinName no name returns all objects', async () => { + it("_serializeObjectsFromPinName no name returns all objects", async () => { const json = item1._toFullJSON(); const LDS = { [DEFAULT_PIN]: [KEY1], [KEY1]: [json], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const results = await LocalDatastore._serializeObjectsFromPinName(null); expect(results).toEqual([json]); @@ -379,71 +393,74 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it('_serializeObjectsFromPinName no objects', async () => { - const object = new ParseObject('Item'); + it("_serializeObjectsFromPinName no objects", async () => { + const object = new ParseObject("Item"); const json = object._toFullJSON(); const LDS = { - [DEFAULT_PIN]: [object.id, 'local10', 'local11'], + [DEFAULT_PIN]: [object.id, "local10", "local11"], [object.id]: [json], randomName: [object.id], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); + const results = await LocalDatastore._serializeObjectsFromPinName( + DEFAULT_PIN + ); expect(results).toEqual([]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it('_serializeObjectsFromPinName with name', async () => { - const obj1 = new ParseObject('Item'); - const obj2 = new ParseObject('Item'); - const obj3 = new ParseObject('Item'); + it("_serializeObjectsFromPinName with name", async () => { + const obj1 = new ParseObject("Item"); + const obj2 = new ParseObject("Item"); + const obj3 = new ParseObject("Item"); const LDS = { [obj1.id]: [obj1._toFullJSON()], [obj2.id]: [obj2._toFullJSON()], [obj3.id]: [obj3._toFullJSON()], - [PIN_PREFIX + 'testPin']: [obj1.id, obj2.id, obj3.id], + [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()]); + const results = await LocalDatastore._serializeObjectsFromPinName( + "testPin" + ); + expect(results).toEqual([ + obj1._toFullJSON(), + obj2._toFullJSON(), + obj3._toFullJSON(), + ]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(3); }); - it('_serializeObjectsFromPinName null pin', async () => { + it("_serializeObjectsFromPinName null pin", async () => { const LDS = { [DEFAULT_PIN]: null, }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); + const results = await LocalDatastore._serializeObjectsFromPinName( + DEFAULT_PIN + ); expect(results).toEqual([]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it('_serializeObject no children', async () => { - const object = new ParseObject('Item'); + it("_serializeObject no children", async () => { + const object = new ParseObject("Item"); object.id = 1234; const json = object._toFullJSON(); const objectKey = `Item_1234`; @@ -452,9 +469,7 @@ describe('LocalDatastore', () => { [objectKey]: [json], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const result = await LocalDatastore._serializeObject(objectKey); expect(result).toEqual(json); @@ -462,8 +477,8 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it('_serializeObject object does not exist', async () => { - const object = new ParseObject('Item'); + it("_serializeObject object does not exist", async () => { + const object = new ParseObject("Item"); object.id = 1234; const objectKey = `Item_1234`; const LDS = {}; @@ -474,14 +489,14 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it('_serializeObject with children', async () => { - const parent = new ParseObject('Item'); + it("_serializeObject with children", async () => { + const parent = new ParseObject("Item"); parent.id = 1234; - const child = new ParseObject('Item'); + const child = new ParseObject("Item"); child.id = 5678; - parent.set('child', child); + parent.set("child", child); const childJSON = child._toFullJSON(); - childJSON.field = 'Serialize Me'; + childJSON.field = "Serialize Me"; const parentKey = LocalDatastore.getKeyForObject(parent); const childKey = LocalDatastore.getKeyForObject(child); @@ -491,9 +506,7 @@ describe('LocalDatastore', () => { [childKey]: [childJSON], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const expectedResults = parent._toFullJSON(); expectedResults.child = childJSON; @@ -501,12 +514,10 @@ describe('LocalDatastore', () => { expect(result).toEqual(expectedResults); }); - it('_destroyObjectIfPinned no objects found in pinName', async () => { + 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 +531,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item1); @@ -533,17 +542,15 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it('_destroyObjectIfPinned no objects found in pinName remove pinName', async () => { + it("_destroyObjectIfPinned no objects found in pinName remove pinName", async () => { const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], - [PIN_PREFIX + 'Custom_Pin']: [KEY2], + [PIN_PREFIX + "Custom_Pin"]: [KEY2], [DEFAULT_PIN]: [KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item2); @@ -554,16 +561,14 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it('_destroyObjectIfPinned', async () => { + it("_destroyObjectIfPinned", async () => { const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], [DEFAULT_PIN]: [KEY1, KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item1); @@ -572,10 +577,12 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(KEY1); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); + expect( + mockLocalStorageController.pinWithName + ).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); }); - it('_traverse', () => { + it("_traverse", () => { // Skip if no objectId const json = item1._toFullJSON(); let encountered = {}; @@ -593,49 +600,47 @@ describe('LocalDatastore', () => { expect(encountered).toEqual({ [KEY1]: json }); // Test if null field exist still encounter - const object = { objectId: 1234, className: 'Item', field: null }; + const object = { objectId: 1234, className: "Item", field: null }; encountered = {}; LocalDatastore._traverse(object, encountered); expect(encountered).toEqual({ [`${OBJECT_PREFIX}Item_1234`]: object }); }); - it('do not sync if disabled', async () => { + it("do not sync if disabled", async () => { LocalDatastore.isEnabled = false; - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); - jest.spyOn(mockLocalStorageController, 'getAllContents'); + jest.spyOn(console, "error").mockImplementationOnce(() => {}); + jest.spyOn(mockLocalStorageController, "getAllContents"); await LocalDatastore.updateFromServer(); expect(LocalDatastore.isSyncing).toBe(false); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it('do not sync if syncing', async () => { + it("do not sync if syncing", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = true; - jest.spyOn(mockLocalStorageController, 'getAllContents'); + jest.spyOn(mockLocalStorageController, "getAllContents"); await LocalDatastore.updateFromServer(); expect(LocalDatastore.isSyncing).toBe(true); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it('updateFromServer empty LDS', async () => { + it("updateFromServer empty LDS", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = {}; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - jest.spyOn(mockLocalStorageController, 'pinWithName'); + jest.spyOn(mockLocalStorageController, "pinWithName"); await LocalDatastore.updateFromServer(); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it('updateFromServer on one object', async () => { + it("updateFromServer on one object", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = { @@ -644,11 +649,9 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - item1.set('updatedField', 'foo'); + item1.set("updatedField", "foo"); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); await LocalDatastore.updateFromServer(); @@ -662,12 +665,12 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it('updateFromServer on user', async () => { + it("updateFromServer on user", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const user = new ParseUser(); - user.id = '1234'; + user.id = "1234"; user._localId = null; const USER_KEY = LocalDatastore.getKeyForObject(user); @@ -677,11 +680,9 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [USER_KEY], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - user.set('updatedField', 'foo'); + user.set("updatedField", "foo"); mockQueryFind.mockImplementationOnce(() => Promise.resolve([user])); await LocalDatastore.updateFromServer(); @@ -695,12 +696,12 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it('updateFromServer ignore unsaved objects', async () => { + it("updateFromServer ignore unsaved objects", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; - const object = new ParseObject('Item'); - object._localId = 'local0'; + const object = new ParseObject("Item"); + object._localId = "local0"; object.id = null; const OBJECT_KEY = LocalDatastore.getKeyForObject(object); @@ -711,11 +712,9 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1, OBJECT_KEY], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - item1.set('updatedField', 'foo'); + item1.set("updatedField", "foo"); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); await LocalDatastore.updateFromServer(); @@ -729,7 +728,7 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it('updateFromServer handle error', async () => { + it("updateFromServer handle error", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = { @@ -738,16 +737,14 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); mockQueryFind.mockImplementationOnce(() => { expect(LocalDatastore.isSyncing).toBe(true); - return Promise.reject('Unable to connect to the Parse API'); + return Promise.reject("Unable to connect to the Parse API"); }); - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + jest.spyOn(console, "error").mockImplementationOnce(() => {}); await LocalDatastore.updateFromServer(); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); @@ -761,10 +758,10 @@ describe('LocalDatastore', () => { expect(LocalDatastore.isSyncing).toBe(false); }); - it('updateFromServer on mixed object', async () => { + it("updateFromServer on mixed object", async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; - const testObject = new ParseObject('TestObject'); + const testObject = new ParseObject("TestObject"); const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], @@ -773,9 +770,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); mockQueryFind .mockImplementationOnce(() => Promise.resolve([item1, item2])) @@ -795,46 +790,55 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(3); }); - it('isLocalDatastoreKey', () => { + it("isLocalDatastoreKey", () => { expect(isLocalDatastoreKey(null)).toBe(false); - expect(isLocalDatastoreKey('')).toBe(false); + expect(isLocalDatastoreKey("")).toBe(false); expect(isLocalDatastoreKey(DEFAULT_PIN)).toBe(true); expect(isLocalDatastoreKey(PIN_PREFIX)).toBe(true); expect(isLocalDatastoreKey(OBJECT_PREFIX)).toBe(true); }); }); -describe('LocalDatastore (BrowserStorageController)', () => { +describe("LocalDatastore (BrowserStorageController)", () => { beforeEach(async () => { CoreManager.setStorageController(BrowserStorageController); CoreManager.setLocalDatastoreController(LocalDatastoreController); await LocalDatastore._clear(); }); - it('can store and retrieve values', async () => { + it("can store and retrieve values", async () => { 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.fromPinWithName(KEY1)).toEqual([ + 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 () => { + it("can remove values", async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ + item1._toFullJSON(), + ]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); expect(await LocalDatastore._getRawStorage()).toEqual({}); }); - it('can handle getAllContent error', async () => { - await LocalDatastore.pinWithName('_default', [{ value: 'WILL_BE_MOCKED' }]); - const windowSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'getItem') + it("can handle getAllContent error", async () => { + await LocalDatastore.pinWithName("_default", [{ value: "WILL_BE_MOCKED" }]); + const windowSpy = jest + .spyOn(Object.getPrototypeOf(window.localStorage), "getItem") .mockImplementationOnce(() => { - return '[1, ]'; + return "[1, ]"; }); - const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + const spy = jest.spyOn(console, "error").mockImplementationOnce(() => {}); const LDS = await LocalDatastore._getAllContents(); expect(LDS).toEqual({}); expect(spy).toHaveBeenCalled(); @@ -842,37 +846,48 @@ describe('LocalDatastore (BrowserStorageController)', () => { windowSpy.mockRestore(); }); - it('can handle store error', async () => { - const windowSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem') + it("can handle store error", async () => { + const windowSpy = jest + .spyOn(Object.getPrototypeOf(window.localStorage), "setItem") .mockImplementationOnce(() => { - throw new Error('error thrown'); + throw new Error("error thrown"); }); - const consoleSpy = jest.spyOn(console, 'log').mockImplementationOnce(() => {}); - await LocalDatastore.pinWithName('myKey', [{ name: 'test' }]); + const consoleSpy = jest + .spyOn(console, "log") + .mockImplementationOnce(() => {}); + await LocalDatastore.pinWithName("myKey", [{ name: "test" }]); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); windowSpy.mockRestore(); }); }); -describe('LocalDatastore (DefaultStorageController)', () => { +describe("LocalDatastore (DefaultStorageController)", () => { beforeEach(async () => { CoreManager.setStorageController(DefaultStorageController); CoreManager.setLocalDatastoreController(LocalDatastoreController); await LocalDatastore._clear(); }); - it('can store and retrieve values', async () => { + it("can store and retrieve values", async () => { 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.fromPinWithName(KEY1)).toEqual([ + 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 () => { + it("can remove values", async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ + item1._toFullJSON(), + ]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); @@ -880,83 +895,91 @@ describe('LocalDatastore (DefaultStorageController)', () => { }); }); -describe('LocalDatastore (RNDatastoreController)', () => { +describe("LocalDatastore (RNDatastoreController)", () => { beforeEach(async () => { CoreManager.setAsyncStorage(mockAsyncStorage); CoreManager.setLocalDatastoreController(RNDatastoreController); await LocalDatastore._clear(); }); - it('can store and retrieve values', async () => { + it("can store and retrieve values", async () => { 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.fromPinWithName(KEY1)).toEqual([ + 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 () => { + it("can remove values", async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ + item1._toFullJSON(), + ]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); expect(await LocalDatastore._getRawStorage()).toEqual({}); }); - it('can handle store error', async () => { + it("can handle store error", async () => { const mockStorageError = { setItem() { - throw new Error('error thrown'); + throw new Error("error thrown"); }, }; - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + jest.spyOn(console, "error").mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); try { - await LocalDatastore.pinWithName('myKey', [{ name: 'test' }]); + await LocalDatastore.pinWithName("myKey", [{ name: "test" }]); } catch (e) { - expect(e.message).toBe('error thrown'); + expect(e.message).toBe("error thrown"); } }); - it('can handle getAllContents undefined', async () => { + it("can handle getAllContents undefined", async () => { await RNDatastoreController.pinWithName(KEY1, undefined); const contents = await RNDatastoreController.getAllContents(); expect(contents[KEY1]).toEqual(null); }); - it('can handle getAllContents non-LDS object', async () => { + it("can handle getAllContents non-LDS object", async () => { await RNDatastoreController.pinWithName(KEY1, item1._toFullJSON()); - await RNDatastoreController.pinWithName('DO_NOT_FETCH', undefined); + await RNDatastoreController.pinWithName("DO_NOT_FETCH", undefined); const contents = await RNDatastoreController.getAllContents(); expect(contents[KEY1]).toEqual(item1._toFullJSON()); - expect(contents['DO_NOT_FETCH']).toBeUndefined(); + expect(contents["DO_NOT_FETCH"]).toBeUndefined(); }); - it('can handle clear error', async () => { + it("can handle clear error", async () => { const mockStorageError = { multiRemove(keys, cb) { - cb('error thrown'); + cb("error thrown"); }, getAllKeys(cb) { - cb(undefined, [KEY1, 'DO_NOT_CLEAR']); - } + cb(undefined, [KEY1, "DO_NOT_CLEAR"]); + }, }; - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + jest.spyOn(console, "error").mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); await LocalDatastore._clear(); }); - it('can handle multiget error', async () => { + it("can handle multiget error", async () => { const mockStorageError = { multiGet(keys, cb) { - cb('error thrown'); + cb("error thrown"); }, getAllKeys(cb) { - cb(undefined, [KEY1, 'DO_NOT_CLEAR']); - } + cb(undefined, [KEY1, "DO_NOT_CLEAR"]); + }, }; - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + jest.spyOn(console, "error").mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); const LDS = await LocalDatastore._getAllContents(); expect(LDS).toEqual({}); diff --git a/src/__tests__/ObjectStateMutations-test.js b/src/__tests__/ObjectStateMutations-test.js index 5162de908..d5b315ac3 100644 --- a/src/__tests__/ObjectStateMutations-test.js +++ b/src/__tests__/ObjectStateMutations-test.js @@ -7,27 +7,27 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParseRelation'); -jest.dontMock('../TaskQueue'); - -const mockObject = function(className) { +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParseRelation"); +jest.dontMock("../TaskQueue"); + +const mockObject = function (className) { this.className = className; }; -mockObject.registerSubclass = function() {}; -jest.setMock('../ParseObject', mockObject); +mockObject.registerSubclass = function () {}; +jest.setMock("../ParseObject", mockObject); -const ObjectStateMutations = require('../ObjectStateMutations'); -const ParseOps = require('../ParseOp'); -const TaskQueue = require('../TaskQueue'); +const ObjectStateMutations = require("../ObjectStateMutations"); +const ParseOps = require("../ParseOp"); +const TaskQueue = require("../TaskQueue"); -describe('ObjectStateMutations', () => { - it('can apply server data', () => { +describe("ObjectStateMutations", () => { + it("can apply server data", () => { const serverData = {}; ObjectStateMutations.setServerData(serverData, { counter: 12 }); expect(serverData).toEqual({ counter: 12 }); @@ -35,21 +35,21 @@ describe('ObjectStateMutations', () => { expect(serverData).toEqual({}); }); - it('can set a pending op', () => { + it("can set a pending op", () => { let pendingOps = [{}]; const op = new ParseOps.IncrementOp(1); - ObjectStateMutations.setPendingOp(pendingOps, 'counter', op); + ObjectStateMutations.setPendingOp(pendingOps, "counter", op); expect(pendingOps).toEqual([{ counter: op }]); pendingOps = [{}, {}]; - ObjectStateMutations.setPendingOp(pendingOps, 'counter', op); + ObjectStateMutations.setPendingOp(pendingOps, "counter", op); expect(pendingOps).toEqual([{}, { counter: op }]); - ObjectStateMutations.setPendingOp(pendingOps, 'counter', null); + ObjectStateMutations.setPendingOp(pendingOps, "counter", null); expect(pendingOps).toEqual([{}, {}]); }); - it('can push a new pending state', () => { + it("can push a new pending state", () => { const pendingOps = [{}]; ObjectStateMutations.pushPendingState(pendingOps); expect(pendingOps).toEqual([{}, {}]); @@ -58,7 +58,7 @@ describe('ObjectStateMutations', () => { expect(pendingOps).toEqual([{}, {}, {}]); }); - it('can pop a pending state', () => { + it("can pop a pending state", () => { let pendingOps = [{}]; let first = pendingOps[0]; expect(ObjectStateMutations.popPendingState(pendingOps)).toBe(first); @@ -71,87 +71,179 @@ describe('ObjectStateMutations', () => { expect(pendingOps).toEqual([{}, {}]); }); - it('can merge the first op set into the next', () => { - let pendingOps = [{ counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp('foo') }, {}]; + 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') }]); - - pendingOps = [{ counter: new ParseOps.SetOp(1) }, { counter: new ParseOps.IncrementOp(1)}]; + expect(pendingOps).toEqual([ + { counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp("foo") }, + ]); + + pendingOps = [ + { counter: new ParseOps.SetOp(1) }, + { counter: new ParseOps.IncrementOp(1) }, + ]; ObjectStateMutations.mergeFirstPendingState(pendingOps); expect(pendingOps).toEqual([{ counter: new ParseOps.SetOp(2) }]); }); - it('can estimate an attribute value', () => { + 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'); + 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"); pendingOps.push({ likes: new ParseOps.RelationOp([], []) }); - 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'); + 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"); }); - it('can estimate all attributes', () => { + 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({ + const pendingOps = [ + { counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp("foo") }, + ]; + 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'); - expect(attributes.likes.parent.id).toBe('someId'); - expect(attributes.likes.parent.className).toBe('someClass'); - expect(attributes.likes.key).toBe('likes'); + 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"); }); - 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({ + 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({ objectField: { counter: 12, - letter: 'a' + letter: "a", }, }); - pendingOps = [{ 'objectField.counter': new ParseOps.SetOp(20) }]; - expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({ + pendingOps = [{ "objectField.counter": new ParseOps.SetOp(20) }]; + expect( + ObjectStateMutations.estimateAttributes( + serverData, + pendingOps, + "someClass", + "someId" + ) + ).toEqual({ objectField: { counter: 20, - letter: 'a' + letter: "a", }, }); }); - it('can commit changes from the server', () => { + it("can commit changes from the server", () => { const serverData = {}; const objectCache = {}; - ObjectStateMutations.commitServerChanges(serverData, objectCache, { name: 'foo', data: { count: 5 } }); - expect(serverData).toEqual({ 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}' }); }); - it('can generate a default state for implementations', () => { + it("can generate a default state for implementations", () => { expect(ObjectStateMutations.defaultState()).toEqual({ serverData: {}, 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..ea85e1c2c 100644 --- a/src/__tests__/OfflineQuery-test.js +++ b/src/__tests__/OfflineQuery-test.js @@ -9,253 +9,260 @@ jest.autoMockOff(); -const matchesQuery = require('../OfflineQuery').matchesQuery; -const validateQuery = require('../OfflineQuery').validateQuery; -const ParseError = require('../ParseError').default; -const ParseObject = require('../ParseObject').default; -const ParseQuery = require('../ParseQuery').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -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'); +const matchesQuery = require("../OfflineQuery").matchesQuery; +const validateQuery = require("../OfflineQuery").validateQuery; +const ParseError = require("../ParseError").default; +const ParseObject = require("../ParseObject").default; +const ParseQuery = require("../ParseQuery").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +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"); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - expect(matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where)).toBe(true); + expect( + matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where) + ).toBe(true); }); - it('can handle unknown query', () => { - const obj = new ParseObject('Item'); - const q = new ParseQuery('Item'); - q._addCondition('key', 'unknown', 'value'); + it("can handle unknown query", () => { + const obj = new ParseObject("Item"); + const q = new ParseQuery("Item"); + q._addCondition("key", "unknown", "value"); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - expect(matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where)).toBe(false); + expect( + matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where) + ).toBe(false); }); - it('matches queries null field', () => { - const obj = new ParseObject('Item'); - const q = new ParseQuery('Item'); - q.equalTo('field', null); + it("matches queries null field", () => { + const obj = new ParseObject("Item"); + const q = new ParseQuery("Item"); + q.equalTo("field", null); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it('matches queries invalid key', () => { - const obj = new ParseObject('Item'); - const q = new ParseQuery('Item'); - q.equalTo('$foo', 'bar'); + it("matches queries invalid key", () => { + const obj = new ParseObject("Item"); + 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'); + expect(e.message).toBe("Invalid Key: $foo"); } }); - it('matches queries date field', () => { + it("matches queries date field", () => { const date = new Date(); - const obj = new ParseObject('Item'); - obj.set('field', date) - const q = new ParseQuery('Item'); - q.greaterThanOrEqualTo('field', date); + const obj = new ParseObject("Item"); + obj.set("field", date); + const q = new ParseQuery("Item"); + q.greaterThanOrEqualTo("field", date); expect(matchesQuery(q.className, obj, [], q)).toBe(true); }); - it('matches queries relation', () => { - const obj = new ParseObject('Item'); + it("matches queries relation", () => { + const obj = new ParseObject("Item"); const relation = obj.relation("author"); const q = relation.query(); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it('matches existence queries', () => { - const obj = new ParseObject('Item'); - obj.set('count', 100); - const q = new ParseQuery('Item'); - q.exists('count'); + it("matches existence queries", () => { + const obj = new ParseObject("Item"); + obj.set("count", 100); + const q = new ParseQuery("Item"); + q.exists("count"); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.exists('name'); + q.exists("name"); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it('matches queries with doesNotExist constraint', () => { - const obj = new ParseObject('Item'); - obj.set('count', 100); + it("matches queries with doesNotExist constraint", () => { + const obj = new ParseObject("Item"); + obj.set("count", 100); - let q = new ParseQuery('Item'); - q.doesNotExist('name'); + let q = new ParseQuery("Item"); + q.doesNotExist("name"); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery('Item'); - q.doesNotExist('count'); + q = new ParseQuery("Item"); + q.doesNotExist("count"); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it('matches on equality queries', () => { + it("matches on equality queries", () => { const day = new Date(); const location = new ParseGeoPoint({ latitude: 37.484815, longitude: -122.148377, }); - const obj = new ParseObject('Person'); + const obj = new ParseObject("Person"); obj - .set('score', 12) - .set('name', 'Bill') - .set('birthday', day) - .set('lastLocation', location); + .set("score", 12) + .set("name", "Bill") + .set("birthday", day) + .set("lastLocation", location); - let q = new ParseQuery('Person'); - q.equalTo('score', 12); + let q = new ParseQuery("Person"); + q.equalTo("score", 12); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery('Person'); - q.equalTo('name', 'Bill'); + q = new ParseQuery("Person"); + q.equalTo("name", "Bill"); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo('name', 'Jeff'); + q.equalTo("name", "Jeff"); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q = new ParseQuery('Person'); - q.containedIn('name', ['Adam', 'Ben', 'Charles']); + q = new ParseQuery("Person"); + q.containedIn("name", ["Adam", "Ben", "Charles"]); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q.containedIn('name', ['Adam', 'Bill', 'Charles']); + q.containedIn("name", ["Adam", "Bill", "Charles"]); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery('Person'); - q.notContainedIn('name', ['Adam', 'Bill', 'Charles']); + q = new ParseQuery("Person"); + q.notContainedIn("name", ["Adam", "Bill", "Charles"]); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q.notContainedIn('name', ['Adam', 'Ben', 'Charles']); + q.notContainedIn("name", ["Adam", "Ben", "Charles"]); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery('Person'); - q.equalTo('birthday', day); + q = new ParseQuery("Person"); + q.equalTo("birthday", day); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo('birthday', new Date(1990, 1)); + q.equalTo("birthday", new Date(1990, 1)); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q = new ParseQuery('Person'); - q.equalTo('lastLocation', location); + 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('score', 12); - q.equalTo('name', 'Bill'); - q.equalTo('birthday', day); + q.equalTo( + "lastLocation", + new ParseGeoPoint({ + latitude: 37.484815, + longitude: -122.148377, + }) + ); + q.equalTo("score", 12); + q.equalTo("name", "Bill"); + q.equalTo("birthday", day); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo('name', 'bill'); + q.equalTo("name", "bill"); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - let img = new ParseObject('Image'); - img.set('tags', ['nofilter', 'latergram', 'tbt']); + let img = new ParseObject("Image"); + img.set("tags", ["nofilter", "latergram", "tbt"]); - q = new ParseQuery('Image'); - q.equalTo('tags', 'selfie'); + q = new ParseQuery("Image"); + q.equalTo("tags", "selfie"); expect(matchesQuery(q.className, img, [], q)).toBe(false); - q.equalTo('tags', 'tbt'); + q.equalTo("tags", "tbt"); expect(matchesQuery(q.className, img, [], q)).toBe(true); - const q2 = new ParseQuery('Image'); - q2.containsAll('tags', ['latergram', 'nofilter']); + const q2 = new ParseQuery("Image"); + q2.containsAll("tags", ["latergram", "nofilter"]); expect(matchesQuery(q.className, img, [], q2)).toBe(true); - q2.containsAll('tags', ['latergram', 'selfie']); + q2.containsAll("tags", ["latergram", "selfie"]); expect(matchesQuery(q.className, img, [], q2)).toBe(false); const u = new ParseUser(); - u.id = 'U2'; - q = new ParseQuery('Image'); - q.equalTo('owner', u); + u.id = "U2"; + q = new ParseQuery("Image"); + q.equalTo("owner", u); - img = new ParseObject('Image'); - img.set('owner', u); + img = new ParseObject("Image"); + img.set("owner", u); expect(matchesQuery(q.className, img, [], q)).toBe(true); let json = img.toJSON(); - json.owner.objectId = 'U3'; + json.owner.objectId = "U3"; expect(matchesQuery(json, q)).toBe(false); // pointers in arrays - q = new ParseQuery('Image'); - q.equalTo('owners', u); + q = new ParseQuery("Image"); + q.equalTo("owners", u); - img = new ParseObject('Image'); - img.set('owners', [u]); + img = new ParseObject("Image"); + img.set("owners", [u]); expect(matchesQuery(q.className, img, [], q)).toBe(true); json = img.toJSON(); - json.owners[0].objectId = 'U3'; + json.owners[0].objectId = "U3"; expect(matchesQuery(json, q)).toBe(false); const u3 = new ParseUser(); - u3.id = 'U3'; - img = new ParseObject('Image'); - img.set('owners', [u3]); + u3.id = "U3"; + img = new ParseObject("Image"); + img.set("owners", [u3]); expect(matchesQuery(q.className, img, [], q)).toBe(false); }); - it('matches on inequalities', () => { - const player = new ParseObject('Person'); + it("matches on inequalities", () => { + const player = new ParseObject("Person"); player - .set('score', 12) - .set('name', 'Bill') - .set('birthday', new Date(1980, 2, 4)); + .set("score", 12) + .set("name", "Bill") + .set("birthday", new Date(1980, 2, 4)); - let q = new ParseQuery('Person'); - q.lessThan('score', 15); + let q = new ParseQuery("Person"); + q.lessThan("score", 15); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThan('score', 10); + q.lessThan("score", 10); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery('Person'); - q.lessThanOrEqualTo('score', 15); + q = new ParseQuery("Person"); + q.lessThanOrEqualTo("score", 15); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThanOrEqualTo('score', 12); + q.lessThanOrEqualTo("score", 12); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThanOrEqualTo('score', 10); + q.lessThanOrEqualTo("score", 10); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery('Person'); - q.greaterThan('score', 15); + q = new ParseQuery("Person"); + q.greaterThan("score", 15); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.greaterThan('score', 10); + q.greaterThan("score", 10); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery('Person'); - q.greaterThanOrEqualTo('score', 15); + q = new ParseQuery("Person"); + q.greaterThanOrEqualTo("score", 15); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.greaterThanOrEqualTo('score', 12); + q.greaterThanOrEqualTo("score", 12); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.greaterThanOrEqualTo('score', 10); + q.greaterThanOrEqualTo("score", 10); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery('Person'); - q.notEqualTo('score', 12); + q = new ParseQuery("Person"); + q.notEqualTo("score", 12); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.notEqualTo('score', 40); + q.notEqualTo("score", 40); expect(matchesQuery(q.className, player, [], q)).toBe(true); }); - it('matches an $or query', () => { - const player = new ParseObject('Player'); - 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('name', 'Player 2'); - const q3 = new ParseQuery('Player'); - q3.equalTo('name', 'Player 3'); + it("matches an $or query", () => { + const player = new ParseObject("Player"); + 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("name", "Player 2"); + const q3 = new ParseQuery("Player"); + q3.equalTo("name", "Player 3"); const orQuery1 = ParseQuery.or(q, q2); const orQuery2 = ParseQuery.or(q2, q3); expect(matchesQuery(q.className, player, [], q)).toBe(true); @@ -264,18 +271,16 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, player, [], orQuery2)).toBe(false); }); - it('matches an $and query', () => { - const player = new ParseObject('Player'); - 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); - const q3 = new ParseQuery('Player'); - q3.equalTo('score', 100); + it("matches an $and query", () => { + const player = new ParseObject("Player"); + 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); + const q3 = new ParseQuery("Player"); + q3.equalTo("score", 100); const andQuery1 = ParseQuery.and(q, q2); const andQuery2 = ParseQuery.and(q, q3); expect(matchesQuery(q.className, player, [], q)).toBe(true); @@ -284,18 +289,16 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, player, [], andQuery2)).toBe(false); }); - it('matches an $nor query', () => { - const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + it("matches an $nor query", () => { + const player = new ParseObject("Player"); + 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('name', 'Player 2'); - const q3 = new ParseQuery('Player'); - q3.equalTo('name', 'Player 3'); + const q = new ParseQuery("Player"); + q.equalTo("name", "Player 1"); + const q2 = new ParseQuery("Player"); + q2.equalTo("name", "Player 2"); + const q3 = new ParseQuery("Player"); + q3.equalTo("name", "Player 3"); const norQuery1 = ParseQuery.nor(q, q2); const norQuery2 = ParseQuery.nor(q2, q3); @@ -306,112 +309,111 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, player, [], norQuery2)).toBe(true); }); - it('matches $regex queries', () => { - const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + it("matches $regex queries", () => { + const player = new ParseObject("Player"); + player.set("score", 12).set("name", "Player 1"); - let q = new ParseQuery('Player'); - q.startsWith('name', 'Play'); + let q = new ParseQuery("Player"); + q.startsWith("name", "Play"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.startsWith('name', 'Ploy'); + q.startsWith("name", "Ploy"); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery('Player'); - q.endsWith('name', ' 1'); + q = new ParseQuery("Player"); + q.endsWith("name", " 1"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.endsWith('name', ' 2'); + q.endsWith("name", " 2"); expect(matchesQuery(q.className, player, [], q)).toBe(false); // Check that special characters are escaped - player.set('name', 'Android-7'); - q = new ParseQuery('Player'); - q.contains('name', 'd-7'); + player.set("name", "Android-7"); + q = new ParseQuery("Player"); + q.contains("name", "d-7"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery('Player'); - q.matches('name', /A.d/, 'm'); + q = new ParseQuery("Player"); + q.matches("name", /A.d/, "m"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.matches('name', /A[^n]d/); + q.matches("name", /A[^n]d/); expect(matchesQuery(q.className, player, [], q)).toBe(false); // Check that the string \\E is returned to normal - player.set('name', 'Slash \\E'); - q = new ParseQuery('Player'); - q.endsWith('name', 'h \\E'); + player.set("name", "Slash \\E"); + q = new ParseQuery("Player"); + q.endsWith("name", "h \\E"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.endsWith('name', 'h \\Ee'); + q.endsWith("name", "h \\Ee"); expect(matchesQuery(q.className, player, [], q)).toBe(false); - player.set('name', 'Slash \\Q and more'); - q = new ParseQuery('Player'); - q.contains('name', 'h \\Q and'); + player.set("name", "Slash \\Q and more"); + q = new ParseQuery("Player"); + q.contains("name", "h \\Q and"); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.contains('name', 'h \\Q or'); + q.contains("name", "h \\Q or"); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery('Player'); - q._addCondition('status', '$regex', { test: function() { return true } }); + q = new ParseQuery("Player"); + q._addCondition("status", "$regex", { + test: function () { + return true; + }, + }); expect(matchesQuery(q.className, player, [], q)).toBe(true); }); - it('matches $nearSphere queries', () => { - let q = new ParseQuery('Checkin'); - q.near('location', new ParseGeoPoint(20, 20)); + it("matches $nearSphere queries", () => { + let q = new ParseQuery("Checkin"); + q.near("location", new ParseGeoPoint(20, 20)); // With no max distance, any GeoPoint is 'near' - const pt = new ParseObject('Checkin'); - pt.set('location', new ParseGeoPoint(40, 40)); + const pt = new ParseObject("Checkin"); + pt.set("location", new ParseGeoPoint(40, 40)); - const ptUndefined = new ParseObject('Checkin'); + const ptUndefined = new ParseObject("Checkin"); - const ptNull = new ParseObject('Checkin'); - ptNull.set('location', null); + const ptNull = new ParseObject("Checkin"); + ptNull.set("location", null); expect(matchesQuery(q.className, pt, [], q)).toBe(true); expect(matchesQuery(q.className, ptUndefined, [], q)).toBe(false); expect(matchesQuery(q.className, ptNull, [], q)).toBe(false); - q = new ParseQuery('Checkin'); - pt.set('location', new ParseGeoPoint(40, 40)); + q = new ParseQuery("Checkin"); + pt.set("location", new ParseGeoPoint(40, 40)); - q.withinRadians('location', new ParseGeoPoint(30, 30), 0.3); + q.withinRadians("location", new ParseGeoPoint(30, 30), 0.3); expect(matchesQuery(q.className, pt, [], q)).toBe(true); - q.withinRadians('location', new ParseGeoPoint(30, 30), 0.2); + q.withinRadians("location", new ParseGeoPoint(30, 30), 0.2); expect(matchesQuery(q.className, pt, [], q)).toBe(false); - q = new ParseQuery('Checkin'); - q._addCondition('location', '$maxDistance', 100); + q = new ParseQuery("Checkin"); + q._addCondition("location", "$maxDistance", 100); expect(matchesQuery(q.className, pt, [], q)).toBe(true); }); - it('matches $within queries', () => { - const caltrainStation = new ParseObject('Checkin'); + it("matches $within queries", () => { + const caltrainStation = new ParseObject("Checkin"); caltrainStation - .set('name', 'Caltrain') - .set('location', new ParseGeoPoint(37.776346, -122.394218)); + .set("name", "Caltrain") + .set("location", new ParseGeoPoint(37.776346, -122.394218)); - const santaClara = new ParseObject('Checkin'); + const santaClara = new ParseObject("Checkin"); santaClara - .set('name', 'Santa Clara') - .set('location', new ParseGeoPoint(37.325635, -121.945753)); + .set("name", "Santa Clara") + .set("location", new ParseGeoPoint(37.325635, -121.945753)); - const noLocation = new ParseObject('Checkin'); - noLocation.set('name', 'Santa Clara'); + const noLocation = new ParseObject("Checkin"); + noLocation.set("name", "Santa Clara"); - const nullLocation = new ParseObject('Checkin'); - nullLocation - .set('name', 'Santa Clara') - .set('location', null); + const nullLocation = new ParseObject("Checkin"); + nullLocation.set("name", "Santa Clara").set("location", null); - - let q = new ParseQuery('Checkin').withinGeoBox( - 'location', + 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); @@ -419,293 +421,375 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, noLocation, [], q)).toBe(false); expect(matchesQuery(q.className, nullLocation, [], q)).toBe(false); // Invalid rectangles - q = new ParseQuery('Checkin').withinGeoBox( - 'location', + 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); expect(matchesQuery(q.className, santaClara, [], q)).toBe(false); - q = new ParseQuery('Checkin').withinGeoBox( - 'location', + 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); expect(matchesQuery(q.className, santaClara, [], q)).toBe(false); }); - it('matches on subobjects with dot notation', () => { - const message = new ParseObject('Message'); - message - .set('test', 'content') - .set('status', { x: 'read', y: 'delivered' }); + it("matches on subobjects with dot notation", () => { + const message = new ParseObject("Message"); + message.set("test", "content").set("status", { x: "read", y: "delivered" }); - let q = new ParseQuery('Message'); - q.equalTo('status.x', 'read'); + let q = new ParseQuery("Message"); + q.equalTo("status.x", "read"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.equalTo('status.z', 'read'); + q = new ParseQuery("Message"); + q.equalTo("status.z", "read"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.equalTo('status.x', 'delivered'); + q = new ParseQuery("Message"); + q.equalTo("status.x", "delivered"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.notEqualTo('status.x', 'read'); + q = new ParseQuery("Message"); + q.notEqualTo("status.x", "read"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.notEqualTo('status.z', 'read'); + q = new ParseQuery("Message"); + q.notEqualTo("status.z", "read"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.notEqualTo('status.x', 'delivered'); + q = new ParseQuery("Message"); + q.notEqualTo("status.x", "delivered"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.exists('status.x'); + q = new ParseQuery("Message"); + q.exists("status.x"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.exists('status.z'); + q = new ParseQuery("Message"); + q.exists("status.z"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.exists('nonexistent.x'); + q = new ParseQuery("Message"); + q.exists("nonexistent.x"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.doesNotExist('status.x'); + q = new ParseQuery("Message"); + q.doesNotExist("status.x"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q.doesNotExist('status.z'); + q = new ParseQuery("Message"); + q.doesNotExist("status.z"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.doesNotExist('nonexistent.z'); + q = new ParseQuery("Message"); + q.doesNotExist("nonexistent.z"); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.equalTo('status.x', 'read'); - q.doesNotExist('status.y'); + q = new ParseQuery("Message"); + q.equalTo("status.x", "read"); + q.doesNotExist("status.y"); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery('Message'); - q._addCondition('status', '$exists', 'invalid'); + q = new ParseQuery("Message"); + q._addCondition("status", "$exists", "invalid"); expect(matchesQuery(q.className, message, [], q)).toBe(true); }); - it('should support containedIn with pointers', () => { - const profile = new ParseObject('Profile'); - profile.id = 'abc'; - const message = new ParseObject('Message'); - message.set('profile', profile); - - let q = new ParseQuery('Message'); - q.containedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'abc' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'def' })]); + it("should support containedIn with pointers", () => { + const profile = new ParseObject("Profile"); + profile.id = "abc"; + const message = new ParseObject("Message"); + message.set("profile", profile); + + let q = new ParseQuery("Message"); + 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 = new ParseQuery("Message"); + q.containedIn("profile", [ + ParseObject.fromJSON({ className: "Profile", objectId: "ghi" }), + ParseObject.fromJSON({ className: "Profile", objectId: "def" }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it('should support notContainedIn with pointers', () => { - const profile = new ParseObject('Profile'); - profile.id = 'abc'; - let message = new ParseObject('Message'); - message.id = 'O1'; - message.set('profile', profile); - - let q = new ParseQuery('Message'); - q.notContainedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' })]); + it("should support notContainedIn with pointers", () => { + const profile = new ParseObject("Profile"); + profile.id = "abc"; + let message = new ParseObject("Message"); + message.id = "O1"; + message.set("profile", profile); + + let q = new ParseQuery("Message"); + 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' })]); + 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" }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it('should support containedIn queries with [objectId]', () => { - const profile = new ParseObject('Profile'); - profile.id = 'abc'; - let message = new ParseObject('Message'); - message.set('profile', profile); + it("should support containedIn queries with [objectId]", () => { + const profile = new ParseObject("Profile"); + profile.id = "abc"; + let message = new ParseObject("Message"); + message.set("profile", profile); - let q = new ParseQuery('Message'); - q.containedIn('profile', ['abc', 'def']); + let q = new ParseQuery("Message"); + q.containedIn("profile", ["abc", "def"]); expect(matchesQuery(q.className, message, [], q)).toBe(true); - profile.id = 'ghi'; - message = new ParseObject('Message'); - message.set('profile', profile); + profile.id = "ghi"; + message = new ParseObject("Message"); + message.set("profile", profile); - q = new ParseQuery('Message'); - q.containedIn('profile', ['abc', 'def']); + q = new ParseQuery("Message"); + q.containedIn("profile", ["abc", "def"]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it('should support notContainedIn queries with [objectId]', () => { - const profile = new ParseObject('Profile'); - profile.id = 'ghi'; - const message = new ParseObject('Message'); - message.set('profile', profile); + it("should support notContainedIn queries with [objectId]", () => { + const profile = new ParseObject("Profile"); + profile.id = "ghi"; + const message = new ParseObject("Message"); + message.set("profile", profile); - let q = new ParseQuery('Message'); - q.notContainedIn('profile', ['abc', 'def']); + let q = new ParseQuery("Message"); + q.notContainedIn("profile", ["abc", "def"]); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery('Message'); - q.notContainedIn('profile', ['abc', 'def', 'ghi']); + q = new ParseQuery("Message"); + q.notContainedIn("profile", ["abc", "def", "ghi"]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it('should support matchesKeyInQuery', () => { - const restaurant = new ParseObject('Restaurant'); - restaurant.set('ratings', 5); - restaurant.set('location', 'Earth'); - const person1 = new ParseObject('Person'); - person1.set('hometown', 'Earth'); - const person2 = new ParseObject('Person'); - person2.set('hometown', 'Mars'); - - let query = new ParseQuery('Restaurant'); - query.greaterThan('rating', 4); - 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, [], mainQuery)).toBe(false); - - query = new ParseQuery('Restaurant'); - query.greaterThan('rating', 4); - 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, [], mainQuery)).toBe(false); + it("should support matchesKeyInQuery", () => { + const restaurant = new ParseObject("Restaurant"); + restaurant.set("ratings", 5); + restaurant.set("location", "Earth"); + const person1 = new ParseObject("Person"); + person1.set("hometown", "Earth"); + const person2 = new ParseObject("Person"); + person2.set("hometown", "Mars"); + + let query = new ParseQuery("Restaurant"); + query.greaterThan("rating", 4); + 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, [], mainQuery)).toBe( + false + ); + + query = new ParseQuery("Restaurant"); + query.greaterThan("rating", 4); + 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, [], mainQuery)).toBe( + false + ); }); - it('should support matchesQuery', () => { + it("should support matchesQuery", () => { const parentObjects = []; const childObjects = []; for (let i = 0; i < 10; i += 1) { - const child = new ParseObject('ChildObject'); + const child = new ParseObject("ChildObject"); child.id = 100 + i; - child.set('x', i); - const parent = new ParseObject('ParentObject'); + child.set("x", i); + const parent = new ParseObject("ParentObject"); parent.id = 10 + i; - parent.set('child', child); + parent.set("child", child); childObjects.push(child); parentObjects.push(parent); } - let subQuery = new ParseQuery('ChildObject'); - 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); + let subQuery = new ParseQuery("ChildObject"); + 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], [], 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); + 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], [], q)).toBe(true); }); - it('should support containedBy query', () => { - const obj1 = new ParseObject('Numbers'); - const obj2 = new ParseObject('Numbers'); - const obj3 = new ParseObject('Numbers'); - obj1.set('numbers', [0, 1, 2]); - obj2.set('numbers', [2, 0]); - obj3.set('numbers', [1, 2, 3, 4]); + it("should support containedBy query", () => { + const obj1 = new ParseObject("Numbers"); + const obj2 = new ParseObject("Numbers"); + const obj3 = new ParseObject("Numbers"); + obj1.set("numbers", [0, 1, 2]); + obj2.set("numbers", [2, 0]); + obj3.set("numbers", [1, 2, 3, 4]); - const q = new ParseQuery('Numbers'); - q.containedBy('numbers', [1, 2, 3, 4, 5]); + const q = new ParseQuery("Numbers"); + q.containedBy("numbers", [1, 2, 3, 4, 5]); expect(matchesQuery(q.className, obj1, [], q)).toBe(false); expect(matchesQuery(q.className, obj2, [], q)).toBe(false); expect(matchesQuery(q.className, obj3, [], q)).toBe(true); }); - it('should support withinPolygon query', () => { - const sacramento = new ParseObject('Location'); - sacramento.set('location', new ParseGeoPoint(38.52, -121.50)); - sacramento.set('name', 'Sacramento'); + it("should support withinPolygon query", () => { + const sacramento = new ParseObject("Location"); + sacramento.set("location", new ParseGeoPoint(38.52, -121.5)); + sacramento.set("name", "Sacramento"); - const honolulu = new ParseObject('Location'); - honolulu.set('location', new ParseGeoPoint(21.35, -157.93)); - honolulu.set('name', 'Honolulu'); + const honolulu = new ParseObject("Location"); + honolulu.set("location", new ParseGeoPoint(21.35, -157.93)); + honolulu.set("name", "Honolulu"); - const sf = new ParseObject('Location'); - sf.set('location', new ParseGeoPoint(37.75, -122.68)); - sf.set('name', 'San Francisco') + const sf = new ParseObject("Location"); + sf.set("location", new ParseGeoPoint(37.75, -122.68)); + 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); + const q = new ParseQuery("Location"); + q.withinPolygon("location", points); expect(matchesQuery(q.className, sacramento, [], q)).toBe(false); expect(matchesQuery(q.className, honolulu, [], q)).toBe(false); expect(matchesQuery(q.className, sf, [], q)).toBe(true); }); - 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]]; + 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 polygon1 = new ParsePolygon(p1); const polygon2 = new ParsePolygon(p2); const polygon3 = new ParsePolygon(p3); - const obj1 = new ParseObject('Bounds'); - const obj2 = new ParseObject('Bounds'); - const obj3 = new ParseObject('Bounds'); - obj1.set('polygon', polygon1); - obj2.set('polygon', polygon2); - obj3.set('polygon', polygon3); + const obj1 = new ParseObject("Bounds"); + const obj2 = new ParseObject("Bounds"); + const obj3 = new ParseObject("Bounds"); + obj1.set("polygon", polygon1); + obj2.set("polygon", polygon2); + obj3.set("polygon", polygon3); const point = new ParseGeoPoint(0.5, 0.5); - const q = new ParseQuery('Bounds'); - q.polygonContains('polygon', point); + const q = new ParseQuery("Bounds"); + q.polygonContains("polygon", point); expect(matchesQuery(q.className, obj1, [], q)).toBe(true); expect(matchesQuery(q.className, obj2, [], q)).toBe(true); expect(matchesQuery(q.className, obj3, [], q)).toBe(false); }); - it('should validate query', () => { - let query = new ParseQuery('TestObject'); - query.equalTo('foo', 'bar'); + it("should validate query", () => { + let query = new ParseQuery("TestObject"); + query.equalTo("foo", "bar"); try { validateQuery(query); validateQuery(query.toJSON()); - query.matches('myString', 'football', 'm'); + query.matches("myString", "football", "m"); validateQuery(query); expect(true).toBe(true); @@ -714,8 +798,8 @@ describe('OfflineQuery', () => { expect(false).toEqual(true); } - query = new ParseQuery('TestObject'); - query.matches('myString', 'football', 'some invalid thing'); + query = new ParseQuery("TestObject"); + query.matches("myString", "football", "some invalid thing"); try { validateQuery(query); expect(true).toBe(false); @@ -723,8 +807,8 @@ describe('OfflineQuery', () => { expect(e.code).toEqual(ParseError.INVALID_QUERY); } - query = new ParseQuery('TestObject'); - query.equalTo('$foo', 'bar'); + query = new ParseQuery("TestObject"); + query.equalTo("$foo", "bar"); try { validateQuery(query); expect(true).toBe(false); diff --git a/src/__tests__/Parse-test.js b/src/__tests__/Parse-test.js index 97256cdd6..ecddb9498 100644 --- a/src/__tests__/Parse-test.js +++ b/src/__tests__/Parse-test.js @@ -7,189 +7,189 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../CryptoController'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../Parse'); -jest.dontMock('../LocalDatastore'); -jest.dontMock('crypto-js/aes'); - -const CoreManager = require('../CoreManager'); -const Parse = require('../Parse'); - -describe('Parse module', () => { - it('can be initialized with keys', () => { - Parse.initialize('A', 'B'); - expect(CoreManager.get('APPLICATION_ID')).toBe('A'); - expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('B'); - - Parse._initialize('A', 'B', 'C'); - expect(CoreManager.get('APPLICATION_ID')).toBe('A'); - expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('B'); - expect(CoreManager.get('MASTER_KEY')).toBe('C'); - }); - - it('enables master key use in the node build', () => { - expect(typeof Parse.Cloud.useMasterKey).toBe('function'); +jest.dontMock("../CoreManager"); +jest.dontMock("../CryptoController"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../Parse"); +jest.dontMock("../LocalDatastore"); +jest.dontMock("crypto-js/aes"); + +const CoreManager = require("../CoreManager"); +const Parse = require("../Parse"); + +describe("Parse module", () => { + it("can be initialized with keys", () => { + Parse.initialize("A", "B"); + expect(CoreManager.get("APPLICATION_ID")).toBe("A"); + expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("B"); + + Parse._initialize("A", "B", "C"); + expect(CoreManager.get("APPLICATION_ID")).toBe("A"); + expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("B"); + expect(CoreManager.get("MASTER_KEY")).toBe("C"); + }); + + it("enables master key use in the node build", () => { + expect(typeof Parse.Cloud.useMasterKey).toBe("function"); Parse.Cloud.useMasterKey(); - expect(CoreManager.get('USE_MASTER_KEY')).toBe(true); + expect(CoreManager.get("USE_MASTER_KEY")).toBe(true); }); - it('exposes certain keys as properties', () => { - Parse.applicationId = '123'; - expect(CoreManager.get('APPLICATION_ID')).toBe('123'); - expect(Parse.applicationId).toBe('123'); + it("exposes certain keys as properties", () => { + Parse.applicationId = "123"; + expect(CoreManager.get("APPLICATION_ID")).toBe("123"); + expect(Parse.applicationId).toBe("123"); - Parse.javaScriptKey = '456'; - expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('456'); - expect(Parse.javaScriptKey).toBe('456'); + Parse.javaScriptKey = "456"; + expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("456"); + expect(Parse.javaScriptKey).toBe("456"); - Parse.masterKey = '789'; - expect(CoreManager.get('MASTER_KEY')).toBe('789'); - expect(Parse.masterKey).toBe('789'); + Parse.masterKey = "789"; + expect(CoreManager.get("MASTER_KEY")).toBe("789"); + expect(Parse.masterKey).toBe("789"); - Parse.serverURL = 'http://example.com'; - expect(CoreManager.get('SERVER_URL')).toBe('http://example.com'); - expect(Parse.serverURL).toBe('http://example.com'); + Parse.serverURL = "http://example.com"; + expect(CoreManager.get("SERVER_URL")).toBe("http://example.com"); + expect(Parse.serverURL).toBe("http://example.com"); - Parse.liveQueryServerURL = 'https://example.com'; - expect(CoreManager.get('LIVEQUERY_SERVER_URL')).toBe('https://example.com'); - expect(Parse.liveQueryServerURL).toBe('https://example.com'); + Parse.liveQueryServerURL = "https://example.com"; + expect(CoreManager.get("LIVEQUERY_SERVER_URL")).toBe("https://example.com"); + expect(Parse.liveQueryServerURL).toBe("https://example.com"); }); - it('can set auth type and token', () => { - Parse.serverAuthType = 'bearer'; - expect(CoreManager.get('SERVER_AUTH_TYPE')).toBe('bearer'); - expect(Parse.serverAuthType).toBe('bearer'); + it("can set auth type and token", () => { + Parse.serverAuthType = "bearer"; + expect(CoreManager.get("SERVER_AUTH_TYPE")).toBe("bearer"); + expect(Parse.serverAuthType).toBe("bearer"); - Parse.serverAuthToken = 'some_token'; - expect(CoreManager.get('SERVER_AUTH_TOKEN')).toBe('some_token'); - expect(Parse.serverAuthToken).toBe('some_token'); + Parse.serverAuthToken = "some_token"; + expect(CoreManager.get("SERVER_AUTH_TOKEN")).toBe("some_token"); + expect(Parse.serverAuthToken).toBe("some_token"); }); - it('can set idempotency', () => { + it("can set idempotency", () => { expect(Parse.idempotency).toBe(false); Parse.idempotency = true; - expect(CoreManager.get('IDEMPOTENCY')).toBe(true); + expect(CoreManager.get("IDEMPOTENCY")).toBe(true); expect(Parse.idempotency).toBe(true); Parse.idempotency = false; expect(Parse.idempotency).toBe(false); }); - it('can set LocalDatastoreController', () => { + 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); }); - it('can set AsyncStorage', () => { + 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); expect(CoreManager.getAsyncStorage()).toBe(controller); }); - it('can enable LocalDatastore', () => { - jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + it("can enable LocalDatastore", () => { + jest.spyOn(console, "log").mockImplementationOnce(() => {}); Parse.LocalDatastore.isEnabled = false; Parse.enableLocalDatastore(); expect(Parse.LocalDatastore.isEnabled).toBe(true); expect(Parse.isLocalDatastoreEnabled()).toBe(true); }); - it('can dump LocalDatastore', async () => { + it("can dump LocalDatastore", async () => { Parse.LocalDatastore.isEnabled = false; let LDS = await Parse.dumpLocalDatastore(); expect(LDS).toEqual({}); Parse.LocalDatastore.isEnabled = true; const controller = { - fromPinWithName: function() {}, - pinWithName: function() {}, - unPinWithName: function() {}, - getAllContents: function() { - return Promise.resolve({ key: 'value' }); + fromPinWithName: function () {}, + pinWithName: function () {}, + unPinWithName: function () {}, + getAllContents: function () { + return Promise.resolve({ key: "value" }); }, - clear: function() {} + clear: function () {}, }; Parse.setLocalDatastoreController(controller); LDS = await Parse.dumpLocalDatastore(); - expect(LDS).toEqual({ key: 'value' }); + expect(LDS).toEqual({ key: "value" }); }); - it('can enable encrypter CurrentUser', () => { - jest.spyOn(console, 'log').mockImplementationOnce(() => {}); - process.env.PARSE_BUILD = 'browser'; + it("can enable encrypter CurrentUser", () => { + jest.spyOn(console, "log").mockImplementationOnce(() => {}); + process.env.PARSE_BUILD = "browser"; Parse.encryptedUser = false; Parse.enableEncryptedUser(); expect(Parse.encryptedUser).toBe(true); expect(Parse.isEncryptedUserEnabled()).toBe(true); }); - it('can set an encrypt token as String', () => { - Parse.secret = 'My Super secret key'; - expect(CoreManager.get('ENCRYPTED_KEY')).toBe('My Super secret key'); - expect(Parse.secret).toBe('My Super secret key'); + it("can set an encrypt token as String", () => { + Parse.secret = "My Super secret key"; + expect(CoreManager.get("ENCRYPTED_KEY")).toBe("My Super secret key"); + expect(Parse.secret).toBe("My Super secret key"); }); - it('can set and get request batch size', () => { - expect(CoreManager.get('REQUEST_BATCH_SIZE')).toBe(20); - CoreManager.set('REQUEST_BATCH_SIZE', 4); - expect(CoreManager.get('REQUEST_BATCH_SIZE')).toBe(4); - CoreManager.set('REQUEST_BATCH_SIZE', 20); + it("can set and get request batch size", () => { + expect(CoreManager.get("REQUEST_BATCH_SIZE")).toBe(20); + CoreManager.set("REQUEST_BATCH_SIZE", 4); + expect(CoreManager.get("REQUEST_BATCH_SIZE")).toBe(4); + CoreManager.set("REQUEST_BATCH_SIZE", 20); }); - it('_request', () => { + it("_request", () => { const controller = { request: jest.fn(), ajax: jest.fn(), }; CoreManager.setRESTController(controller); - Parse._request('POST', 'classes/TestObject'); + Parse._request("POST", "classes/TestObject"); const [method, path] = controller.request.mock.calls[0]; - expect(method).toBe('POST'); - expect(path).toBe('classes/TestObject'); + expect(method).toBe("POST"); + expect(path).toBe("classes/TestObject"); }); - it('_ajax', () => { + it("_ajax", () => { const controller = { request: jest.fn(), ajax: jest.fn(), }; CoreManager.setRESTController(controller); - Parse._ajax('POST', 'classes/TestObject'); + Parse._ajax("POST", "classes/TestObject"); const [method, path] = controller.ajax.mock.calls[0]; - expect(method).toBe('POST'); - expect(path).toBe('classes/TestObject'); + expect(method).toBe("POST"); + expect(path).toBe("classes/TestObject"); }); - it('_getInstallationId', () => { + it("_getInstallationId", () => { const controller = { - currentInstallationId: () => '1234', + currentInstallationId: () => "1234", }; CoreManager.setInstallationController(controller); - expect(Parse._getInstallationId()).toBe('1234'); + expect(Parse._getInstallationId()).toBe("1234"); }); - it('_decode', () => { + it("_decode", () => { expect(Parse._decode(null, 12)).toBe(12); }); - it('_encode', () => { + it("_encode", () => { expect(Parse._encode(12)).toBe(12); }); }); diff --git a/src/__tests__/ParseACL-test.js b/src/__tests__/ParseACL-test.js index d9935dd5d..5046316e6 100644 --- a/src/__tests__/ParseACL-test.js +++ b/src/__tests__/ParseACL-test.js @@ -7,204 +7,204 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../ParseACL'); +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); +}; +jest.setMock("../ParseRole", mockRole); -const ParseACL = require('../ParseACL').default; -const ParseUser = require('../ParseUser').default; -const ParseRole = require('../ParseRole'); +const ParseACL = require("../ParseACL").default; +const ParseUser = require("../ParseUser").default; +const ParseRole = require("../ParseRole"); -describe('ParseACL', () => { - it('can be constructed with no arguments', () => { +describe("ParseACL", () => { + it("can be constructed with no arguments", () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); }); - it('can be constructed with a ParseUser', () => { + it("can be constructed with a ParseUser", () => { const u = new ParseUser(); - u.id = 'uid'; + u.id = "uid"; const a = new ParseACL(u); expect(a.permissionsById).toEqual({ uid: { read: true, write: true } }); }); - it('can be constructed with a map of user IDs', () => { + it("can be constructed with a map of user IDs", () => { const a = new ParseACL({ aUserId: { read: true, write: false } }); expect(a.permissionsById).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); - it('throws when constructed with an invalid permissions map', () => { - let err = function() { + it("throws when constructed with an invalid permissions map", () => { + let err = function () { new ParseACL({ aUserId: { foo: true, bar: false } }); }; expect(err).toThrow( - 'Tried to create an ACL with an invalid permission type.' + "Tried to create an ACL with an invalid permission type." ); - err = function() { + err = function () { new ParseACL({ aUserId: { read: 12 } }); }; expect(err).toThrow( - 'Tried to create an ACL with an invalid permission value.' + "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() { }); - }).toThrow('ParseACL constructed with a function. Did you forget ()?'); + it("throws a helpful error when constructed with a function", () => { + expect(function () { + new ParseACL(function () {}); + }).toThrow("ParseACL constructed with a function. Did you forget ()?"); }); - it('throws when setting an invalid user id', () => { + 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.' + "userId must be a string." ); expect(() => { - a.getReadAccess(new ParseUser(), true) - }).toThrow('Cannot get access for a ParseUser without an ID'); + a.getReadAccess(new ParseUser(), true); + }).toThrow("Cannot get access for a ParseUser without an ID"); }); - it('throws when setting an invalid access', () => { + 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', () => { + it("throws when role does not have name", () => { const a = new ParseACL(); expect(() => { - a.setReadAccess(new ParseRole(), true) - }).toThrow('Role must have a name'); + a.setReadAccess(new ParseRole(), true); + }).toThrow("Role must have a name"); expect(() => { - a.getReadAccess(new ParseRole(), true) - }).toThrow('Role must have a name'); + a.getReadAccess(new ParseRole(), true); + }).toThrow("Role must have a name"); }); - it('throws when setting an invalid role', () => { + 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' + "role must be a ParseRole or a String" ); expect(a.setRoleWriteAccess.bind(a, 12, true)).toThrow( - 'role must be a ParseRole or a String' + "role must be a ParseRole or a String" ); }); - it('can be rendered to JSON format', () => { + it("can be rendered to JSON format", () => { const a = new ParseACL({ aUserId: { read: true, write: false } }); expect(a.toJSON()).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); - it('can set read access for a user', () => { + it("can set read access for a user", () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); // removing a permission that doesn't exist does nothing - a.setReadAccess('aUserId', false); + a.setReadAccess("aUserId", false); expect(a.permissionsById).toEqual({}); - a.setReadAccess('aUserId', true); + a.setReadAccess("aUserId", true); expect(a.permissionsById).toEqual({ aUserId: { - read: true - } + read: true, + }, }); - a.setReadAccess('aUserId', false); + a.setReadAccess("aUserId", false); expect(a.permissionsById).toEqual({}); }); - it('can get read access for a user', () => { + it("can get read access for a user", () => { const a = new ParseACL({ aUserId: { read: true, - write: false - } + write: false, + }, }); - expect(a.getReadAccess('aUserId')).toBe(true); + expect(a.getReadAccess("aUserId")).toBe(true); }); - it('can set write access for a user', () => { + it("can set write access for a user", () => { const a = new ParseACL(); const u = new ParseUser(); - u.id = 'aUserId'; + u.id = "aUserId"; expect(a.permissionsById).toEqual({}); // removing a permission that doesn't exist does nothing - a.setWriteAccess('aUserId', false); + a.setWriteAccess("aUserId", false); expect(a.permissionsById).toEqual({}); a.setWriteAccess(u, false); expect(a.permissionsById).toEqual({}); - a.setWriteAccess('aUserId', true); + a.setWriteAccess("aUserId", true); expect(a.permissionsById).toEqual({ aUserId: { - write: true - } + write: true, + }, }); - a.setWriteAccess('aUserId', false); + a.setWriteAccess("aUserId", false); expect(a.permissionsById).toEqual({}); a.setWriteAccess(u, true); expect(a.permissionsById).toEqual({ aUserId: { - write: true - } + write: true, + }, }); a.setWriteAccess(u, false); expect(a.permissionsById).toEqual({}); }); - it('can get write access for a user', () => { + it("can get write access for a user", () => { const a = new ParseACL({ aUserId: { read: true, - write: false - } + write: false, + }, }); const u = new ParseUser(); - u.id = 'aUserId'; + u.id = "aUserId"; - expect(a.getWriteAccess('aUserId')).toBe(false); + expect(a.getWriteAccess("aUserId")).toBe(false); expect(a.getWriteAccess(u)).toBe(false); }); - it('can set public read access', () => { + it("can set public read access", () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); expect(a.getPublicReadAccess()).toBe(false); a.setPublicReadAccess(true); expect(a.permissionsById).toEqual({ - '*': { - read: true - } + "*": { + read: true, + }, }); expect(a.getPublicReadAccess()).toBe(true); @@ -212,16 +212,16 @@ describe('ParseACL', () => { expect(a.permissionsById).toEqual({}); }); - it('can set public write access', () => { + it("can set public write access", () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); expect(a.getPublicWriteAccess()).toBe(false); a.setPublicWriteAccess(true); expect(a.permissionsById).toEqual({ - '*': { - write: true - } + "*": { + write: true, + }, }); expect(a.getPublicWriteAccess()).toBe(true); @@ -229,77 +229,77 @@ describe('ParseACL', () => { expect(a.permissionsById).toEqual({}); }); - it('can get role read access', () => { + it("can get role read access", () => { const a = new ParseACL({ - 'role:admin': { + "role:admin": { read: true, - write: true - } + write: true, + }, }); - expect(a.getRoleReadAccess('admin')).toBe(true); - expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(true); - expect(a.getReadAccess(new ParseRole('admin'))).toBe(true); + expect(a.getRoleReadAccess("admin")).toBe(true); + expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(true); + expect(a.getReadAccess(new ParseRole("admin"))).toBe(true); }); - it('can get role write access', () => { + it("can get role write access", () => { const a = new ParseACL({ - 'role:admin': { + "role:admin": { read: true, - write: true - } + write: true, + }, }); - expect(a.getRoleWriteAccess('admin')).toBe(true); - expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(true); - expect(a.getWriteAccess(new ParseRole('admin'))).toBe(true); + expect(a.getRoleWriteAccess("admin")).toBe(true); + expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(true); + expect(a.getWriteAccess(new ParseRole("admin"))).toBe(true); }); - it('throws when fetching an invalid role', () => { + 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' + "role must be a ParseRole or a String" ); expect(a.getRoleWriteAccess.bind(null, 5)).toThrow( - 'role must be a ParseRole or a String' + "role must be a ParseRole or a String" ); }); - it('can set role read access', () => { + it("can set role read access", () => { const a = new ParseACL(); - expect(a.getRoleReadAccess('admin')).toBe(false); - expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(false); + expect(a.getRoleReadAccess("admin")).toBe(false); + expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(false); - a.setRoleReadAccess('admin', true); - expect(a.getRoleReadAccess('admin')).toBe(true); - expect(a.getRoleWriteAccess('admin')).toBe(false); + a.setRoleReadAccess("admin", true); + expect(a.getRoleReadAccess("admin")).toBe(true); + expect(a.getRoleWriteAccess("admin")).toBe(false); - a.setRoleReadAccess(new ParseRole('admin'), false); - expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(false); + a.setRoleReadAccess(new ParseRole("admin"), false); + expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(false); - a.setReadAccess(new ParseRole('admin'), true); - expect(a.getReadAccess(new ParseRole('admin'))).toBe(true); + a.setReadAccess(new ParseRole("admin"), true); + expect(a.getReadAccess(new ParseRole("admin"))).toBe(true); }); - it('can set role write access', () => { + it("can set role write access", () => { const a = new ParseACL(); - expect(a.getRoleWriteAccess('admin')).toBe(false); - expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(false); + expect(a.getRoleWriteAccess("admin")).toBe(false); + expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(false); - a.setRoleWriteAccess('admin', true); - expect(a.getRoleWriteAccess('admin')).toBe(true); - expect(a.getRoleReadAccess('admin')).toBe(false); + a.setRoleWriteAccess("admin", true); + expect(a.getRoleWriteAccess("admin")).toBe(true); + expect(a.getRoleReadAccess("admin")).toBe(false); - a.setRoleWriteAccess(new ParseRole('admin'), false); - expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(false); + a.setRoleWriteAccess(new ParseRole("admin"), false); + expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(false); - a.setWriteAccess(new ParseRole('admin'), true); - expect(a.getWriteAccess(new ParseRole('admin'))).toBe(true); + a.setWriteAccess(new ParseRole("admin"), true); + expect(a.getWriteAccess(new ParseRole("admin"))).toBe(true); }); - it('can test equality against another ACL', () => { + it("can test equality against another ACL", () => { const a = new ParseACL(); const b = new ParseACL(); @@ -331,32 +331,32 @@ describe('ParseACL', () => { expect(b.equals(a)).toBe(true); expect(a.equals(new ParseACL())).toBe(true); - a.setReadAccess('aUserId', true); - b.setReadAccess('aUserId', true); + a.setReadAccess("aUserId", true); + b.setReadAccess("aUserId", true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); - a.setWriteAccess('aUserId', true); - b.setWriteAccess('aUserId', true); + a.setWriteAccess("aUserId", true); + b.setWriteAccess("aUserId", true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); - a.setWriteAccess('anotherUserId', true); + a.setWriteAccess("anotherUserId", true); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); - b.setWriteAccess('anotherUserId', true); + b.setWriteAccess("anotherUserId", true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); a.setPublicReadAccess(true); - a.setReadAccess('aUserId', true); - b.setReadAccess('aUserId', true); + a.setReadAccess("aUserId", true); + b.setReadAccess("aUserId", true); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); expect(a.equals({})).toBe(false); - b.setWriteAccess('newUserId', true); + b.setWriteAccess("newUserId", true); expect(a.equals(b)).toBe(false); a.setPublicReadAccess(false); diff --git a/src/__tests__/ParseConfig-test.js b/src/__tests__/ParseConfig-test.js index a468697d1..69c6fc56d 100644 --- a/src/__tests__/ParseConfig-test.js +++ b/src/__tests__/ParseConfig-test.js @@ -7,273 +7,282 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../escape'); -jest.dontMock('../ParseConfig'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../RESTController'); -jest.dontMock('../Storage'); -jest.dontMock('../StorageController.default'); -jest.dontMock('./test_helpers/mockAsyncStorage'); +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../escape"); +jest.dontMock("../ParseConfig"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../RESTController"); +jest.dontMock("../Storage"); +jest.dontMock("../StorageController.default"); +jest.dontMock("./test_helpers/mockAsyncStorage"); -const mockAsyncStorage = require('./test_helpers/mockAsyncStorage'); -const CoreManager = require('../CoreManager'); -const ParseConfig = require('../ParseConfig').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const Storage = require('../Storage'); +const mockAsyncStorage = require("./test_helpers/mockAsyncStorage"); +const CoreManager = require("../CoreManager"); +const ParseConfig = require("../ParseConfig").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const Storage = require("../Storage"); -CoreManager.set('APPLICATION_ID', 'A'); -CoreManager.set('JAVASCRIPT_KEY', 'B'); +CoreManager.set("APPLICATION_ID", "A"); +CoreManager.set("JAVASCRIPT_KEY", "B"); -describe('ParseConfig', () => { +describe("ParseConfig", () => { beforeEach(() => { ParseConfig._clearCache(); }); - it('exposes attributes via get()', () => { + it("exposes attributes via get()", () => { const c = new ParseConfig(); c.attributes = { - str: 'hello', - num: 44 + str: "hello", + num: 44, }; - expect(c.get('str')).toBe('hello'); - expect(c.get('num')).toBe(44); - expect(c.get('nonexistent')).toBe(undefined); + expect(c.get("str")).toBe("hello"); + expect(c.get("num")).toBe(44); + expect(c.get("nonexistent")).toBe(undefined); }); - it('exposes escaped attributes', () => { + it("exposes escaped attributes", () => { const c = new ParseConfig(); c.attributes = { - brackets: '<>', - phone: 'AT&T' + brackets: "<>", + phone: "AT&T", }; - expect(c.escape('brackets')).toBe('<>'); - expect(c.escape('phone')).toBe('AT&T'); - expect(c.escape('phone')).toBe('AT&T'); + expect(c.escape("brackets")).toBe("<>"); + expect(c.escape("phone")).toBe("AT&T"); + expect(c.escape("phone")).toBe("AT&T"); }); - 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 - } - })); + 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, + }, + }) + ); 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), }); }); - it('can handle decodedData error', async () => { + it("can handle decodedData error", async () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); - const path = Storage.generatePath('currentConfig'); + const path = Storage.generatePath("currentConfig"); await Storage.setItemAsync(path, {}); const config = await ParseConfig.current(); expect(config.attributes).toEqual({}); CoreManager.setStorageController(currentStorage); }); - it('can retrieve the current config from async storage', async () => { + it("can retrieve the current config from async storage", async () => { 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 - } - })); + const path = Storage.generatePath("currentConfig"); + 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({ params: { - str: 'hello', + str: "hello", num: 45, file: { - __type: 'File', - name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' - } - } + __type: "File", + name: "parse.txt", + url: "https://files.parsetfss.com/a/parse.txt", + }, + }, }); }, - ajax() {} + ajax() {}, }); ParseConfig.get().then((config) => { - expect(config.get('str')).toBe('hello'); - expect(config.get('num')).toBe(45); - expect(config.get('file').name()).toBe('parse.txt'); - const path = Storage.generatePath('currentConfig'); + expect(config.get("str")).toBe("hello"); + expect(config.get("num")).toBe(45); + expect(config.get("file").name()).toBe("parse.txt"); + const path = Storage.generatePath("currentConfig"); expect(JSON.parse(Storage.getItem(path))).toEqual({ - str: 'hello', + str: "hello", num: 45, file: { - __type: 'File', - name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' - } + __type: "File", + name: "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) => { - expect(config.get('str')).toBe('hello2'); - expect(config.get('num')).toBe(46); - const path = Storage.generatePath('currentConfig'); + 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 + str: "hello2", + num: 46, }); done(); }); }); - it('can save a config object that be retrieved with masterkey only', async () => { + it("can save a config object that be retrieved with masterkey only", async () => { CoreManager.setRESTController({ request(method, path, body, options) { - if (method === 'PUT') { - expect(method).toBe('PUT'); - expect(path).toBe('config'); + if (method === "PUT") { + expect(method).toBe("PUT"); + expect(path).toBe("config"); expect(body).toEqual({ - params: { internal: 'i', number: 12 }, + params: { internal: "i", number: 12 }, masterKeyOnly: { internal: true }, }); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - internal: 'i', - number: 12 + internal: "i", + number: 12, }, result: true, }); - } else if (method === 'GET') { - expect(method).toBe('GET'); - expect(path).toBe('config'); + } else if (method === "GET") { + expect(method).toBe("GET"); + expect(path).toBe("config"); expect(body).toEqual({}); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - internal: 'i', - number: 12 + internal: "i", + number: 12, }, }); } }, - ajax() {} + ajax() {}, }); const config = await ParseConfig.save( - { internal: 'i', number: 12 }, + { internal: "i", number: 12 }, { internal: true } ); - expect(config.get('internal')).toBe('i'); - expect(config.get('number')).toBe(12); + expect(config.get("internal")).toBe("i"); + expect(config.get("number")).toBe(12); }); - it('can get a config object with master key', async () => { + it("can get a config object with master key", async () => { CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('config'); + expect(method).toBe("GET"); + expect(path).toBe("config"); expect(body).toEqual({}); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - str: 'hello', - num: 45 - } + str: "hello", + num: 45, + }, }); }, - ajax() {} + ajax() {}, }); const config = await ParseConfig.get({ useMasterKey: true }); - expect(config.get('str')).toBe('hello'); - expect(config.get('num')).toBe(45); - const path = Storage.generatePath('currentConfig'); + expect(config.get("str")).toBe("hello"); + expect(config.get("num")).toBe(45); + const path = Storage.generatePath("currentConfig"); expect(JSON.parse(Storage.getItem(path))).toEqual({ - str: 'hello', + str: "hello", num: 45, }); }); - 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) => { expect(error.code).toBe(107); - expect(error.message).toBe('Config JSON response invalid.'); + 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'); + return Promise.reject("failure"); }, - ajax() {} + ajax() {}, }); ParseConfig.get().then(null, (error) => { - expect(error).toBe('failure'); + expect(error).toBe("failure"); done(); }); }); diff --git a/src/__tests__/ParseError-test.js b/src/__tests__/ParseError-test.js index 3da9dbbef..893352ba2 100644 --- a/src/__tests__/ParseError-test.js +++ b/src/__tests__/ParseError-test.js @@ -7,23 +7,23 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../ParseError'); +jest.dontMock("../ParseError"); -const ParseError = require('../ParseError').default; +const ParseError = require("../ParseError").default; -describe('ParseError', () => { - it('have sensible string representation', () => { - const error = new ParseError(123, 'some error message'); +describe("ParseError", () => { + it("have sensible string representation", () => { + const error = new ParseError(123, "some error message"); - expect(error.toString()).toMatch('ParseError'); - expect(error.toString()).toMatch('123'); - expect(error.toString()).toMatch('some error message'); + expect(error.toString()).toMatch("ParseError"); + expect(error.toString()).toMatch("123"); + expect(error.toString()).toMatch("some error message"); }); - it('has a proper json representation', () => { - const error = new ParseError(123, 'some error message'); + it("has a proper json representation", () => { + const error = new ParseError(123, "some error message"); expect(JSON.parse(JSON.stringify(error))).toEqual({ - message: 'some error message', + message: "some error message", code: 123, }); }); diff --git a/src/__tests__/ParseFile-test.js b/src/__tests__/ParseFile-test.js index e1c41613a..8434d376e 100644 --- a/src/__tests__/ParseFile-test.js +++ b/src/__tests__/ParseFile-test.js @@ -8,31 +8,31 @@ */ /* global File */ jest.autoMockOff(); -jest.mock('http'); -jest.mock('https'); -jest.mock('../ParseACL'); +jest.mock("http"); +jest.mock("https"); +jest.mock("../ParseACL"); -const ParseError = require('../ParseError').default; -const ParseFile = require('../ParseFile').default; -const b64Digit = require('../ParseFile').b64Digit; +const ParseError = require("../ParseError").default; +const ParseFile = require("../ParseFile").default; +const b64Digit = require("../ParseFile").b64Digit; -const ParseObject = require('../ParseObject').default; -const CoreManager = require('../CoreManager'); -const EventEmitter = require('../EventEmitter'); +const ParseObject = require("../ParseObject").default; +const CoreManager = require("../CoreManager"); +const EventEmitter = require("../EventEmitter"); -const mockHttp = require('http'); -const mockHttps = require('https'); +const mockHttp = require("http"); +const mockHttps = require("https"); const mockLocalDatastore = { _updateLocalIdForObject: jest.fn(), _updateObjectIfPinned: jest.fn(), }; -jest.setMock('../LocalDatastore', mockLocalDatastore); +jest.setMock("../LocalDatastore", mockLocalDatastore); function generateSaveMock(prefix) { - return function(name, payload, options) { - if (options && typeof options.progress === 'function') { - options.progress(0.5, 5, 10, { type: 'upload' }); + return function (name, payload, options) { + if (options && typeof options.progress === "function") { + options.progress(0.5, 5, 10, { type: "upload" }); } return Promise.resolve({ name: name, @@ -43,168 +43,176 @@ function generateSaveMock(prefix) { const defaultController = CoreManager.getFileController(); -describe('ParseFile', () => { +describe("ParseFile", () => { beforeEach(() => { CoreManager.setFileController({ - saveFile: generateSaveMock('http://files.parsetfss.com/a/'), - saveBase64: generateSaveMock('http://files.parsetfss.com/a/'), - download: () => Promise.resolve({ - base64: 'ParseA==', - contentType: 'image/png', - }), + saveFile: generateSaveMock("http://files.parsetfss.com/a/"), + saveBase64: generateSaveMock("http://files.parsetfss.com/a/"), + download: () => + Promise.resolve({ + base64: "ParseA==", + contentType: "image/png", + }), }); }); afterEach(() => { - process.env.PARSE_BUILD = 'node'; + process.env.PARSE_BUILD = "node"; }); - it('can create files with base64 encoding', () => { - const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe(''); + it("can create files with base64 encoding", () => { + const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe(""); }); - it('can extract data type from base64', () => { - const file = new ParseFile('parse.txt', { - base64: 'data:image/png;base64,ParseA==' + it("can extract data type from base64", () => { + const file = new ParseFile("parse.txt", { + base64: "data:image/png;base64,ParseA==", }); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe('image/png'); + 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' }); - expect(file._source.format).toBe('uri'); - expect(file._source.uri).toBe('http://example.com/image.png'); + it("can create files with file uri", () => { + 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==' + 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==", }); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe('audio/m4a'); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe("audio/m4a"); }); - 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==' + 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==", }); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe('application/vnd.google-earth.kml+xml'); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe("application/vnd.google-earth.kml+xml"); }); - 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==' + 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==", }); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe('application/vnd.3gpp.pic-bw-var'); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe("application/vnd.3gpp.pic-bw-var"); }); - it('can create files with byte arrays', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe(''); + it("can create files with byte arrays", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe(""); }); - it('can create files with all types of characters', () => { - const file = new ParseFile('parse.txt', [11, 239, 191, 215, 80, 52]); - expect(file._source.base64).toBe('C++/11A0'); - expect(file._source.type).toBe(''); + it("can create files with all types of characters", () => { + const file = new ParseFile("parse.txt", [11, 239, 191, 215, 80, 52]); + expect(file._source.base64).toBe("C++/11A0"); + expect(file._source.type).toBe(""); }); - it('can create an empty file', () => { - const file = new ParseFile('parse.txt'); - expect(file.name()).toBe('parse.txt'); + it("can create an empty file", () => { + const file = new ParseFile("parse.txt"); + expect(file.name()).toBe("parse.txt"); expect(file.url()).toBe(undefined); }); - it('throws when creating a file with invalid data', () => { - expect(function() { - new ParseFile('parse.txt', 12); - }).toThrow('Cannot create a Parse.File with that data.'); + it("throws when creating a file with invalid data", () => { + expect(function () { + new ParseFile("parse.txt", 12); + }).toThrow("Cannot create a Parse.File with that data."); - expect(function() { - new ParseFile('parse.txt', null); - }).toThrow('Cannot create a Parse.File with that data.'); + expect(function () { + new ParseFile("parse.txt", null); + }).toThrow("Cannot create a Parse.File with that data."); - expect(function() { - new ParseFile('parse.txt', 'string'); - }).toThrow('Cannot create a Parse.File with that data.'); + expect(function () { + new ParseFile("parse.txt", "string"); + }).toThrow("Cannot create a Parse.File with that data."); }); - it('throws with invalid base64', () => { - expect(function() { + it("throws with invalid base64", () => { + expect(function () { b64Digit(65); - }).toThrow('Tried to encode large digit 65 in base64.'); + }).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) { + it("returns secure url when specified", () => { + const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + 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" + ); }); }); - it('returns undefined when there is no url', () => { - const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); + it("returns undefined when there is no url", () => { + const file = new ParseFile("parse.txt", { base64: "ParseA==" }); expect(file.url({ forceSecure: true })).toBeUndefined(); }); - it('updates fields when saved', () => { - const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); - expect(file.name()).toBe('parse.txt'); + it("updates fields when saved", () => { + 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'); + expect(result.name()).toBe("parse.txt"); + expect(result.url()).toBe("http://files.parsetfss.com/a/parse.txt"); }); }); - it('updates fields when saved with uri', () => { - const file = new ParseFile('parse.png', { uri: 'https://example.com/image.png' }); - expect(file.name()).toBe('parse.png'); + it("updates fields when saved with uri", () => { + 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'); + expect(result.name()).toBe("parse.png"); + expect(result.url()).toBe("http://files.parsetfss.com/a/parse.png"); }); }); - it('generates a JSON representation', () => { - const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); - return file.save().then(function(result) { + it("generates a JSON representation", () => { + const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + return file.save().then(function (result) { expect(result.toJSON()).toEqual({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "parse.txt", + url: "http://files.parsetfss.com/a/parse.txt", }); }); }); - it('can construct a file from a JSON object', () => { + it("can construct a file from a JSON object", () => { const f = ParseFile.fromJSON({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "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(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', () => { - let a = new ParseFile('parse.txt', [61, 170, 236, 120]); - let b = new ParseFile('parse.txt', [61, 170, 236, 120]); + it("can test equality against another ParseFile", () => { + let a = new ParseFile("parse.txt", [61, 170, 236, 120]); + let b = new ParseFile("parse.txt", [61, 170, 236, 120]); expect(a.equals(a)).toBe(true); // unsaved files are never equal @@ -212,60 +220,68 @@ describe('ParseFile', () => { expect(b.equals(a)).toBe(false); a = ParseFile.fromJSON({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "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' + __type: "File", + name: "parse.txt", + url: "http://files.parsetfss.com/a/parse.txt", }); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); b = ParseFile.fromJSON({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/b/parse.txt' + __type: "File", + name: "parse.txt", + url: "http://files.parsetfss.com/b/parse.txt", }); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); }); - it('reports progress during save when source is a File', () => { - const file = new ParseFile('progress.txt', new File(["Parse"], "progress.txt")); + it("reports progress during save when source is a File", () => { + const file = new ParseFile( + "progress.txt", + new File(["Parse"], "progress.txt") + ); const options = { - progress: function(){} + progress: function () {}, }; - jest.spyOn(options, 'progress'); + 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'); + expect(f.name()).toBe("progress.txt"); + expect(f.url()).toBe("http://files.parsetfss.com/a/progress.txt"); }); }); - it('can cancel file upload', () => { + it("can cancel file upload", () => { const mockRequestTask = { 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'); + jest.spyOn(mockRequestTask, "abort"); file.cancel(); expect(mockRequestTask.abort).toHaveBeenCalledTimes(0); @@ -276,159 +292,170 @@ describe('ParseFile', () => { expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); }); - it('should save file with metadata and tag options', async () => { + it("should save file with metadata and tag options", async () => { const fileController = { saveFile: jest.fn().mockResolvedValue({}), saveBase64: () => {}, download: () => {}, }; CoreManager.setFileController(fileController); - const file = new ParseFile('donald_duck.txt', new File(['Parse'], 'donald_duck.txt')); - file.addMetadata('foo', 'bar'); - file.addTag('bar', 'foo'); + const file = new ParseFile( + "donald_duck.txt", + new File(["Parse"], "donald_duck.txt") + ); + file.addMetadata("foo", "bar"); + file.addTag("bar", "foo"); await file.save(); expect(fileController.saveFile).toHaveBeenCalledWith( - 'donald_duck.txt', + "donald_duck.txt", { file: expect.any(File), - format: 'file', - type: '' + format: "file", + type: "", }, { - metadata: { foo: 'bar' }, - tags: { bar: 'foo' }, + metadata: { foo: "bar" }, + tags: { bar: "foo" }, requestTask: expect.any(Function), - }, + } ); }); - it('should create new ParseFile with metadata and tags', () => { - const metadata = { foo: 'bar' }; - const tags = { bar: 'foo' }; - const file = new ParseFile('parse.txt', [61, 170, 236, 120], '', metadata, tags); - expect(file._source.base64).toBe('ParseA=='); - expect(file._source.type).toBe(''); + it("should create new ParseFile with metadata and tags", () => { + const metadata = { foo: "bar" }; + const tags = { bar: "foo" }; + const file = new ParseFile( + "parse.txt", + [61, 170, 236, 120], + "", + metadata, + tags + ); + expect(file._source.base64).toBe("ParseA=="); + expect(file._source.type).toBe(""); expect(file.metadata()).toBe(metadata); expect(file.tags()).toBe(tags); }); - it('should set metadata', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.setMetadata({ foo: 'bar' }); - expect(file.metadata()).toEqual({ foo: 'bar' }); + it("should set metadata", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.setMetadata({ foo: "bar" }); + expect(file.metadata()).toEqual({ foo: "bar" }); }); - it('should set metadata key', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.addMetadata('foo', 'bar'); - expect(file.metadata()).toEqual({ foo: 'bar' }); + it("should set metadata key", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.addMetadata("foo", "bar"); + expect(file.metadata()).toEqual({ foo: "bar" }); }); - it('should not set metadata if key is not a string', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.addMetadata(10, ''); + it("should not set metadata if key is not a string", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.addMetadata(10, ""); expect(file.metadata()).toEqual({}); }); - it('should set tags', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.setTags({ foo: 'bar' }); - expect(file.tags()).toEqual({ foo: 'bar' }); + it("should set tags", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.setTags({ foo: "bar" }); + expect(file.tags()).toEqual({ foo: "bar" }); }); - it('should set tag key', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.addTag('foo', 'bar'); - expect(file.tags()).toEqual({ foo: 'bar' }); + it("should set tag key", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.addTag("foo", "bar"); + expect(file.tags()).toEqual({ foo: "bar" }); }); - it('should not set tag if key is not a string', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - file.addTag(10, 'bar'); + it("should not set tag if key is not a string", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + file.addTag(10, "bar"); expect(file.tags()).toEqual({}); }); }); -describe('FileController', () => { +describe("FileController", () => { beforeEach(() => { CoreManager.setFileController(defaultController); - const request = function(method, path) { - const name = path.substr(path.indexOf('/') + 1); + 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 name = path.substr(path.indexOf('/') + 1); + 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 }); }); - it('saves files created with bytes', () => { - const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - return file.save().then(function(f) { + it("saves files created with bytes", () => { + const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + 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'); + expect(f.name()).toBe("parse.txt"); + expect(f.url()).toBe("https://files.parsetfss.com/a/parse.txt"); }); }); - it('saves files via ajax', () => { + it("saves files via ajax", () => { // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile('parse.txt', blob); - file._source.format = 'file'; + 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'); + expect(f.name()).toBe("parse.txt"); + expect(f.url()).toBe("https://files.parsetfss.com/a/parse.txt"); }); }); - it('saveUri with uri type', async () => { - const file = new ParseFile('parse.png', { uri: 'https://example.com/image.png' }); - const spy = jest.spyOn( - defaultController, - 'download' - ) + 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', + base64: "ParseA==", + contentType: "image/png", }); }); - const spy2 = jest.spyOn(defaultController, 'saveBase64'); + const spy2 = jest.spyOn(defaultController, "saveBase64"); await file.save(); expect(defaultController.download).toHaveBeenCalledTimes(1); expect(defaultController.saveBase64).toHaveBeenCalledTimes(1); - expect(defaultController.saveBase64.mock.calls[0][0]).toEqual('parse.png'); + 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' - ) + 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 spy2 = jest.spyOn(defaultController, 'saveBase64'); + const spy2 = jest.spyOn(defaultController, "saveBase64"); await file.save(); expect(defaultController.download).toHaveBeenCalledTimes(1); expect(defaultController.saveBase64).toHaveBeenCalledTimes(0); @@ -436,43 +463,47 @@ describe('FileController', () => { spy2.mockRestore(); }); - it('download with base64 http', async () => { + it("download with base64 http", async () => { 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') + const spy = jest + .spyOn(mockHttp, "get") .mockImplementationOnce((uri, cb) => { cb(mockResponse); - mockResponse.emit('data', 'base64String'); - mockResponse.emit('end'); + mockResponse.emit("data", "base64String"); + mockResponse.emit("end"); return { - on: function() {} + on: function () {}, }; }); - const data = await defaultController.download('http://example.com/image.png'); - expect(data.base64).toBe('base64String'); - expect(data.contentType).toBe('image/png'); + const data = await defaultController.download( + "http://example.com/image.png" + ); + expect(data.base64).toBe("base64String"); + expect(data.contentType).toBe("image/png"); expect(mockHttp.get).toHaveBeenCalledTimes(1); expect(mockHttps.get).toHaveBeenCalledTimes(0); spy.mockRestore(); }); - it('download with base64 http abort', async () => { + it("download with base64 http abort", async () => { defaultController._setXHR(null); const mockRequest = Object.create(EventEmitter.prototype); 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') + const spy = jest + .spyOn(mockHttp, "get") .mockImplementationOnce((uri, cb) => { cb(mockResponse); return mockRequest; @@ -480,128 +511,141 @@ describe('FileController', () => { const options = { requestTask: () => {}, }; - defaultController.download('http://example.com/image.png', options).then((data) => { - expect(data).toEqual({}); - }); - mockRequest.emit('abort'); + defaultController + .download("http://example.com/image.png", options) + .then((data) => { + expect(data).toEqual({}); + }); + mockRequest.emit("abort"); spy.mockRestore(); }); - it('download with base64 https', async () => { + it("download with base64 https", async () => { 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') + const spy = jest + .spyOn(mockHttps, "get") .mockImplementationOnce((uri, cb) => { cb(mockResponse); - mockResponse.emit('data', 'base64String'); - mockResponse.emit('end'); + mockResponse.emit("data", "base64String"); + mockResponse.emit("end"); return { - on: function() {} + on: function () {}, }; }); - const data = await defaultController.download('https://example.com/image.png'); - expect(data.base64).toBe('base64String'); - expect(data.contentType).toBe('image/png'); + const data = await defaultController.download( + "https://example.com/image.png" + ); + expect(data.base64).toBe("base64String"); + expect(data.contentType).toBe("image/png"); expect(mockHttp.get).toHaveBeenCalledTimes(0); expect(mockHttps.get).toHaveBeenCalledTimes(1); spy.mockRestore(); }); - it('download with ajax', async () => { + it("download with ajax", async () => { const mockXHR = function () { 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() { - return 'image/png'; - } + getResponseHeader: function () { + return "image/png"; + }, }; }; defaultController._setXHR(mockXHR); const options = { requestTask: () => {}, }; - const data = await defaultController.download('https://example.com/image.png', options); - expect(data.base64).toBe('ParseA=='); - expect(data.contentType).toBe('image/png'); + const data = await defaultController.download( + "https://example.com/image.png", + options + ); + expect(data.base64).toBe("ParseA=="); + expect(data.contentType).toBe("image/png"); }); - it('download with ajax no response', async () => { + it("download with ajax no response", async () => { const mockXHR = function () { 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() { - return 'image/png'; - } + getResponseHeader: function () { + return "image/png"; + }, }; }; defaultController._setXHR(mockXHR); const options = { requestTask: () => {}, }; - const data = await defaultController.download('https://example.com/image.png', options); + const data = await defaultController.download( + "https://example.com/image.png", + options + ); expect(data).toEqual({}); }); - it('download with ajax abort', async () => { + it("download with ajax abort", async () => { 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() { - return 'image/png'; + 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) => { - expect(data).toEqual({}); - }); + defaultController + .download("https://example.com/image.png", options) + .then((data) => { + expect(data).toEqual({}); + }); _requestTask.abort(); }); - it('download with ajax error', async () => { + it("download with ajax error", async () => { const mockXHR = function () { return { open: jest.fn(), - send: jest.fn().mockImplementation(function() { - this.onerror('error thrown'); - }) + send: jest.fn().mockImplementation(function () { + this.onerror("error thrown"); + }), }; }; defaultController._setXHR(mockXHR); @@ -609,214 +653,219 @@ describe('FileController', () => { requestTask: () => {}, }; try { - await defaultController.download('https://example.com/image.png', options); + await defaultController.download( + "https://example.com/image.png", + options + ); } catch (e) { - expect(e).toBe('error thrown'); + expect(e).toBe("error thrown"); } }); - it('download with xmlhttprequest unsupported', async () => { + it("download with xmlhttprequest unsupported", async () => { defaultController._setXHR(null); - process.env.PARSE_BUILD = 'browser'; + process.env.PARSE_BUILD = "browser"; try { - await defaultController.download('https://example.com/image.png'); + await defaultController.download("https://example.com/image.png"); } catch (e) { - expect(e).toBe('Cannot make a request: No definition of XMLHttpRequest was found.'); + expect(e).toBe( + "Cannot make a request: No definition of XMLHttpRequest was found." + ); } }); - it('getData', async () => { - const file = new ParseFile('parse.png', [61, 170, 236, 120]); + it("getData", async () => { + const file = new ParseFile("parse.png", [61, 170, 236, 120]); const data = await file.getData(); - expect(data).toBe('ParseA=='); + expect(data).toBe("ParseA=="); }); - it('getData unsaved file', async () => { - const file = new ParseFile('parse.png'); + it("getData unsaved file", async () => { + const file = new ParseFile("parse.png"); try { await file.getData(); } catch (e) { - expect(e.message).toBe('Cannot retrieve data for unsaved ParseFile.'); + expect(e.message).toBe("Cannot retrieve data for unsaved ParseFile."); } }); - it('getData via download', async () => { - const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); + it("getData via download", async () => { + const file = new ParseFile("parse.txt", { base64: "ParseA==" }); file._data = null; const result = await file.save(); - const spy = jest.spyOn( - defaultController, - 'download' - ) + const spy = jest + .spyOn(defaultController, "download") .mockImplementationOnce((uri, options) => { options.requestTask(null); return Promise.resolve({ - base64: 'ParseA==', - contentType: 'image/png', + base64: "ParseA==", + contentType: "image/png", }); }); const data = await result.getData(); expect(defaultController.download).toHaveBeenCalledTimes(1); - expect(data).toBe('ParseA=='); + expect(data).toBe("ParseA=="); spy.mockRestore(); }); - it('saves files via ajax with sessionToken option', () => { - const request = function(method, path) { - const name = path.substr(path.indexOf('/') + 1); + it("saves files via ajax with sessionToken option", () => { + 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 name = path.substr(path.indexOf('/') + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile('parse.txt', blob); - file._source.format = 'file'; - - 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'); - }); + const file = new ParseFile("parse.txt", blob); + file._source.format = "file"; + + 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"); + }); }); - it('saves files via ajax currentUser sessionToken', () => { - CoreManager.set('UserController', { + it("saves files via ajax currentUser sessionToken", () => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'currentUserToken'; - } + return "currentUserToken"; + }, }); - } + }, }); - const request = function(method, path) { - const name = path.substr(path.indexOf('/') + 1); + 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 name = path.substr(path.indexOf('/') + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile('parse.txt', blob); - file._source.format = 'file'; + 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'); + expect(f.name()).toBe("parse.txt"); + expect(f.url()).toBe("https://files.parsetfss.com/a/parse.txt"); }); }); - it('should save file using saveFile with metadata and tags', async () => { - CoreManager.set('UserController', { + it("should save file using saveFile with metadata and tags", async () => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'currentUserToken'; - } + return "currentUserToken"; + }, }); - } + }, }); const request = jest.fn((method, path) => { - const name = path.substr(path.indexOf('/') + 1); + 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 name = path.substr(path.indexOf('/') + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile('parse.txt', blob); - file._source.format = 'file'; - file.addMetadata('foo', 'bar'); - file.addTag('bar', 'foo'); + const file = new ParseFile("parse.txt", blob); + file._source.format = "file"; + file.addMetadata("foo", "bar"); + file.addTag("bar", "foo"); const f = await file.save(); expect(f).toBe(file); - expect(f.name()).toBe('parse.txt'); - expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); + expect(f.name()).toBe("parse.txt"); + expect(f.url()).toBe("https://files.parsetfss.com/a/parse.txt"); expect(request).toHaveBeenCalledWith( - 'POST', - 'files/parse.txt', + "POST", + "files/parse.txt", { - base64: 'NjExNzAyMzYxMjA=', + base64: "NjExNzAyMzYxMjA=", fileData: { metadata: { - foo: 'bar', + foo: "bar", }, tags: { - bar: 'foo', + bar: "foo", }, }, }, - { requestTask: expect.any(Function) }, + { requestTask: expect.any(Function) } ); }); - it('saves files via object saveAll options', async () => { + it("saves files via object saveAll options", async () => { const ajax = async () => {}; const request = jest.fn(async (method, path, data, options) => { - if (path.indexOf('files/') === 0) { - expect(options.sessionToken).toBe('testToken'); + if (path.indexOf("files/") === 0) { + expect(options.sessionToken).toBe("testToken"); return { - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + name: "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); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile('parse.txt', blob); - file._source.format = 'file'; - const object = ParseObject.fromJSON({ className: 'TestObject' }); - object.set('file', file); - await ParseObject.saveAll([object], { sessionToken: 'testToken' }); + const file = new ParseFile("parse.txt", blob); + file._source.format = "file"; + const object = ParseObject.fromJSON({ className: "TestObject" }); + object.set("file", file); + await ParseObject.saveAll([object], { sessionToken: "testToken" }); expect(request).toHaveBeenCalled(); }); - it('should throw error if file deleted without name', async (done) => { - const file = new ParseFile('', [1, 2, 3]); + it("should throw error if file deleted without name", async (done) => { + const file = new ParseFile("", [1, 2, 3]); try { await file.destroy(); } catch (e) { @@ -825,79 +874,101 @@ describe('FileController', () => { } }); - it('should delete file', async () => { - const file = new ParseFile('filename', [1, 2, 3]); - const ajax = jest.fn().mockResolvedValueOnce({ foo: 'bar' }); + it("should delete file", async () => { + const file = new ParseFile("filename", [1, 2, 3]); + const ajax = jest.fn().mockResolvedValueOnce({ foo: "bar" }); CoreManager.setRESTController({ ajax, request: () => {} }); 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, - }); + expect(ajax).toHaveBeenCalledWith( + "DELETE", + "https://api.parse.com/1/files/filename", + "", + { + "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.'))); + 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 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, - }); + expect(ajax).toHaveBeenCalledWith( + "DELETE", + "https://api.parse.com/1/files/filename", + "", + { + "X-Parse-Application-ID": null, + "X-Parse-Master-Key": null, + } + ); expect(handleError).toHaveBeenCalled(); }); - it('should handle delete file error invalid server response', async () => { - const file = new ParseFile('filename', [1, 2, 3]); + it("should handle delete file error invalid server response", async () => { + const file = new ParseFile("filename", [1, 2, 3]); const response = null; const ajax = jest.fn().mockResolvedValueOnce(Promise.reject(response)); 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, - }); + expect(ajax).toHaveBeenCalledWith( + "DELETE", + "https://api.parse.com/1/files/filename", + "", + { + "X-Parse-Application-ID": null, + "X-Parse-Master-Key": null, + } + ); expect(handleError).not.toHaveBeenCalled(); }); - - it('controller saveFile format errors', async () => { + 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.'); + expect(e.message).toBe( + "saveFile can only be used with File-type sources." + ); } }); - it('controller saveBase64 format errors', async () => { + 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.'); + expect(e.message).toBe( + "saveBase64 can only be used with Base64-type sources." + ); } }); - it('controller saveFile file reader errors', async () => { + it("controller saveFile file reader errors", async () => { const fileReader = global.FileReader; class FileReader { readAsDataURL() { - this.onerror('Could not load file.'); + this.onerror("Could not load file."); } } 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.'); + expect(e).toBe("Could not load file."); } global.FileReader = fileReader; }); diff --git a/src/__tests__/ParseGeoPoint-test.js b/src/__tests__/ParseGeoPoint-test.js index 70fae22b1..a4555e083 100644 --- a/src/__tests__/ParseGeoPoint-test.js +++ b/src/__tests__/ParseGeoPoint-test.js @@ -9,20 +9,20 @@ jest.autoMockOff(); -const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseGeoPoint = require("../ParseGeoPoint").default; global.navigator.geolocation = { getCurrentPosition: (cb) => { return cb({ coords: { latitude: 10, longitude: 20, - } + }, }); - } -} + }, +}; -describe('GeoPoint', () => { - it('can be constructed from various inputs', () => { +describe("GeoPoint", () => { + it("can be constructed from various inputs", () => { let point = new ParseGeoPoint(); expect(point.latitude).toBe(0); expect(point.longitude).toBe(0); @@ -40,7 +40,7 @@ describe('GeoPoint', () => { expect(point.longitude).toBe(88); }); - it('throws when created with non numbers values', () => { + it("throws when created with non numbers values", () => { [ [NaN, NaN], [false, true], @@ -49,14 +49,14 @@ describe('GeoPoint', () => { ["29", 10], [["29", "10"]], [{ latitude: "29", longitude: "10" }], - ].forEach(case_test => { - expect(function() { + ].forEach((case_test) => { + expect(function () { new ParseGeoPoint(...case_test); - }).toThrow('GeoPoint latitude and longitude must be valid numbers'); + }).toThrow("GeoPoint latitude and longitude must be valid numbers"); }); }); - it('can set latitude and longitude', () => { + it("can set latitude and longitude", () => { const point = new ParseGeoPoint(); expect(point.latitude).toBe(0); expect(point.longitude).toBe(0); @@ -74,7 +74,7 @@ describe('GeoPoint', () => { expect(point.longitude).toBe(14.9); }); - it('throws for points out of bounds', () => { + it("throws for points out of bounds", () => { expect(() => { new ParseGeoPoint(90.01, 0.0); }).toThrow(); @@ -92,7 +92,7 @@ describe('GeoPoint', () => { }).toThrow(); }); - it('can calculate distance in radians', () => { + it("can calculate distance in radians", () => { const d2r = Math.PI / 180.0; const pointA = new ParseGeoPoint(); const pointB = new ParseGeoPoint(); @@ -149,9 +149,9 @@ describe('GeoPoint', () => { expect(pointB.radiansTo(pointA)).toBeCloseTo(1.85, 2); }); - it('can calculate distances in mi and km', () => { + 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); @@ -199,7 +199,7 @@ describe('GeoPoint', () => { expect(sacramento.milesTo(vorkuta)).toBeCloseTo(5159.7, -3); }); - it('can test equality against another GeoPoint', () => { + it("can test equality against another GeoPoint", () => { let a = new ParseGeoPoint(40, 40); expect(a.equals(a)).toBe(true); @@ -225,7 +225,7 @@ describe('GeoPoint', () => { expect(b.equals(a)).toBe(false); }); - it('can get current location', async () => { + it("can get current location", async () => { const geoPoint = ParseGeoPoint.current(); expect(geoPoint.latitude).toBe(10); expect(geoPoint.longitude).toBe(20); diff --git a/src/__tests__/ParseInstallation-test.js b/src/__tests__/ParseInstallation-test.js index ce1b6853d..938beac6c 100644 --- a/src/__tests__/ParseInstallation-test.js +++ b/src/__tests__/ParseInstallation-test.js @@ -1,28 +1,28 @@ -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParseInstallation'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParseInstallation"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../UniqueInstanceStateController"); -const ParseInstallation = require('../ParseInstallation').default; +const ParseInstallation = require("../ParseInstallation").default; -describe('ParseInstallation', () => { - it('can create ParseInstallation', () => { +describe("ParseInstallation", () => { + it("can create ParseInstallation", () => { let installation = new ParseInstallation(); - expect(installation.className).toBe('_Installation'); + expect(installation.className).toBe("_Installation"); installation = new ParseInstallation({}); - expect(installation.className).toBe('_Installation'); + expect(installation.className).toBe("_Installation"); - installation = new ParseInstallation({ deviceToken: 'token' }); - expect(installation.get('deviceToken')).toBe('token'); + installation = new ParseInstallation({ deviceToken: "token" }); + 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..6896f17b9 100644 --- a/src/__tests__/ParseLiveQuery-test.js +++ b/src/__tests__/ParseLiveQuery-test.js @@ -7,194 +7,195 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../ParseLiveQuery'); -jest.dontMock('../CoreManager'); -jest.dontMock('../InstallationController'); -jest.dontMock('../LiveQueryClient'); -jest.dontMock('../LiveQuerySubscription'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseQuery'); -jest.dontMock('../EventEmitter'); -jest.dontMock('../promiseUtils'); +jest.dontMock("../ParseLiveQuery"); +jest.dontMock("../CoreManager"); +jest.dontMock("../InstallationController"); +jest.dontMock("../LiveQueryClient"); +jest.dontMock("../LiveQuerySubscription"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseQuery"); +jest.dontMock("../EventEmitter"); +jest.dontMock("../promiseUtils"); // Forces the loading -const LiveQuery = require('../ParseLiveQuery').default; -const CoreManager = require('../CoreManager'); -const ParseQuery = require('../ParseQuery').default; -const LiveQuerySubscription = require('../LiveQuerySubscription').default; +const LiveQuery = require("../ParseLiveQuery").default; +const CoreManager = require("../CoreManager"); +const ParseQuery = require("../ParseQuery").default; +const LiveQuerySubscription = require("../LiveQuerySubscription").default; const mockLiveQueryClient = { open: jest.fn(), close: jest.fn(), }; -describe('ParseLiveQuery', () => { +describe("ParseLiveQuery", () => { beforeEach(() => { const controller = CoreManager.getLiveQueryController(); controller._clearCachedDefaultClient(); - CoreManager.set('InstallationController', { + CoreManager.set("InstallationController", { currentInstallationId() { - return Promise.resolve('1234'); - } + return Promise.resolve("1234"); + }, }); }); - it('fails with an invalid livequery server url', (done) => { - CoreManager.set('UserController', { + it("fails with an invalid livequery server url", (done) => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve(undefined); - } + }, }); - CoreManager.set('LIVEQUERY_SERVER_URL', 'notaurl'); + CoreManager.set("LIVEQUERY_SERVER_URL", "notaurl"); const controller = CoreManager.getLiveQueryController(); controller.getDefaultLiveQueryClient().catch((err) => { expect(err.message).toBe( - 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' + "You need to set a proper Parse LiveQuery server url before using LiveQueryClient" ); done(); }); }); - it('initializes the client', (done) => { - CoreManager.set('UserController', { + 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'); + 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) => { - expect(client.serverURL).toBe('wss://live.example.com/parse'); - expect(client.applicationId).toBe('appid'); - expect(client.javascriptKey).toBe('jskey'); + expect(client.serverURL).toBe("wss://live.example.com/parse"); + expect(client.applicationId).toBe("appid"); + expect(client.javascriptKey).toBe("jskey"); expect(client.sessionToken).toBe(undefined); - expect(client.installationId).toBe('1234'); + expect(client.installationId).toBe("1234"); expect(client.additionalProperties).toBe(true); done(); }); }); - it('automatically generates a ws websocket url', (done) => { - CoreManager.set('UserController', { + 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); + 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) => { - expect(client.serverURL).toBe('ws://api.parse.com/1'); - expect(client.applicationId).toBe('appid'); - expect(client.javascriptKey).toBe('jskey'); + expect(client.serverURL).toBe("ws://api.parse.com/1"); + expect(client.applicationId).toBe("appid"); + expect(client.javascriptKey).toBe("jskey"); expect(client.sessionToken).toBe(undefined); done(); }); }); - it('automatically generates a wss websocket url', (done) => { - CoreManager.set('UserController', { + 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); + 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) => { - expect(client.serverURL).toBe('wss://api.parse.com/1'); - expect(client.applicationId).toBe('appid'); - expect(client.javascriptKey).toBe('jskey'); + expect(client.serverURL).toBe("wss://api.parse.com/1"); + expect(client.applicationId).toBe("appid"); + expect(client.javascriptKey).toBe("jskey"); expect(client.sessionToken).toBe(undefined); done(); }); }); - it('populates the session token', (done) => { - CoreManager.set('UserController', { + it("populates the session token", (done) => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); - CoreManager.set('APPLICATION_ID', 'appid'); - CoreManager.set('JAVASCRIPT_KEY', 'jskey'); - CoreManager.set('LIVEQUERY_SERVER_URL', null); + CoreManager.set("APPLICATION_ID", "appid"); + CoreManager.set("JAVASCRIPT_KEY", "jskey"); + CoreManager.set("LIVEQUERY_SERVER_URL", null); const controller = CoreManager.getLiveQueryController(); controller.getDefaultLiveQueryClient().then((client) => { - expect(client.serverURL).toBe('wss://api.parse.com/1'); - expect(client.applicationId).toBe('appid'); - expect(client.javascriptKey).toBe('jskey'); - expect(client.sessionToken).toBe('token'); + expect(client.serverURL).toBe("wss://api.parse.com/1"); + expect(client.applicationId).toBe("appid"); + expect(client.javascriptKey).toBe("jskey"); + expect(client.sessionToken).toBe("token"); done(); }); }); - it('handle LiveQueryClient events', async () => { - const spy = jest.spyOn(LiveQuery, 'emit'); + it("handle LiveQueryClient events", async () => { + const spy = jest.spyOn(LiveQuery, "emit"); - CoreManager.set('UserController', { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); - CoreManager.set('APPLICATION_ID', 'appid'); - CoreManager.set('JAVASCRIPT_KEY', 'jskey'); - CoreManager.set('LIVEQUERY_SERVER_URL', null); + CoreManager.set("APPLICATION_ID", "appid"); + CoreManager.set("JAVASCRIPT_KEY", "jskey"); + CoreManager.set("LIVEQUERY_SERVER_URL", null); const controller = CoreManager.getLiveQueryController(); const client = await controller.getDefaultLiveQueryClient(); - client.emit('error', 'error thrown'); - client.emit('open'); - client.emit('close'); - expect(spy.mock.calls[0]).toEqual(['error', 'error thrown']); - expect(spy.mock.calls[1]).toEqual(['open']); - expect(spy.mock.calls[2]).toEqual(['close']); + client.emit("error", "error thrown"); + client.emit("open"); + client.emit("close"); + expect(spy.mock.calls[0]).toEqual(["error", "error thrown"]); + expect(spy.mock.calls[1]).toEqual(["open"]); + expect(spy.mock.calls[2]).toEqual(["close"]); spy.mockRestore(); }); - it('subscribes to all subscription events', (done) => { - CoreManager.set('UserController', { + it("subscribes to all subscription events", (done) => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); - CoreManager.set('APPLICATION_ID', 'appid'); - CoreManager.set('JAVASCRIPT_KEY', 'jskey'); - CoreManager.set('LIVEQUERY_SERVER_URL', null); + CoreManager.set("APPLICATION_ID", "appid"); + CoreManager.set("JAVASCRIPT_KEY", "jskey"); + CoreManager.set("LIVEQUERY_SERVER_URL", null); 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"); const isCalled = {}; - ["open", + [ + "open", "close", "error", "create", "update", "enter", "leave", - "delete"].forEach((key) =>{ + "delete", + ].forEach((key) => { ourSubscription.on(key, () => { isCalled[key] = true; }); @@ -205,8 +206,8 @@ describe('ParseLiveQuery', () => { setTimeout(() => { try { client.socket = { - send() {} - } + send() {}, + }; client.connectPromise.resolve(); const actualSubscription = client.subscriptions.get(1); @@ -237,31 +238,31 @@ describe('ParseLiveQuery', () => { expect(isCalled["delete"]).toBe(true); done(); - } catch(e){ + } catch (e) { done.fail(e); } }, 1); }); }); - it('should not throw on usubscribe', (done) => { - CoreManager.set('UserController', { + it("should not throw on usubscribe", (done) => { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); const query = new ParseQuery("ObjectType"); query.equalTo("test", "value"); - const subscription = new LiveQuerySubscription('0', query, 'token'); + const subscription = new LiveQuerySubscription("0", query, "token"); subscription.unsubscribe().then(done).catch(done.fail); }); - it('can handle LiveQuery open event', async () => { - jest.spyOn(mockLiveQueryClient, 'open'); + it("can handle LiveQuery open event", async () => { + jest.spyOn(mockLiveQueryClient, "open"); const controller = CoreManager.getLiveQueryController(); controller.setDefaultLiveQueryClient(mockLiveQueryClient); @@ -269,8 +270,8 @@ describe('ParseLiveQuery', () => { expect(mockLiveQueryClient.open).toHaveBeenCalled(); }); - it('can handle LiveQuery close event', async () => { - jest.spyOn(mockLiveQueryClient, 'close'); + it("can handle LiveQuery close event", async () => { + jest.spyOn(mockLiveQueryClient, "close"); const controller = CoreManager.getLiveQueryController(); controller.setDefaultLiveQueryClient(mockLiveQueryClient); @@ -278,9 +279,9 @@ describe('ParseLiveQuery', () => { expect(mockLiveQueryClient.close).toHaveBeenCalled(); }); - it('can handle LiveQuery error event', async () => { + it("can handle LiveQuery error event", async () => { try { - LiveQuery.emit('error'); + LiveQuery.emit("error"); expect(true).toBe(true); } catch (error) { // Should not throw error diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 8118552c5..ff930f4b7 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -7,41 +7,41 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../arrayContainsObject'); -jest.dontMock('../canBeSerialized'); -jest.dontMock('../CoreManager'); -jest.dontMock('../promiseUtils'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../equals'); -jest.dontMock('../escape'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../parseDate'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParsePolygon'); -jest.dontMock('../ParseRelation'); -jest.dontMock('../RESTController'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../TaskQueue'); -jest.dontMock('../unique'); -jest.dontMock('../UniqueInstanceStateController'); -jest.dontMock('../unsavedChildren'); -jest.dontMock('../ParseACL'); -jest.dontMock('../LocalDatastore'); - -jest.mock('uuid/v4', () => { +jest.dontMock("../arrayContainsObject"); +jest.dontMock("../canBeSerialized"); +jest.dontMock("../CoreManager"); +jest.dontMock("../promiseUtils"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../equals"); +jest.dontMock("../escape"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../parseDate"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParsePolygon"); +jest.dontMock("../ParseRelation"); +jest.dontMock("../RESTController"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../TaskQueue"); +jest.dontMock("../unique"); +jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock("../unsavedChildren"); +jest.dontMock("../ParseACL"); +jest.dontMock("../LocalDatastore"); + +jest.mock("uuid/v4", () => { let value = 0; return () => value++; }); -jest.dontMock('./test_helpers/mockXHR'); +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,32 +49,32 @@ 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 + __type: "Relation", + 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.' + "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.' + "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.' + "Internal Error. Relation retrieved from two different Objects." ); } } else if (parent.id) { @@ -84,38 +84,40 @@ mockRelation.prototype._ensureParentAndKey = function(parent, key) { this.parent = parent; } }; -jest.setMock('../ParseRelation', mockRelation); +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 - })); + 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); }; -jest.setMock('../ParseQuery', mockQuery); +jest.setMock("../ParseQuery", mockQuery); -import { DEFAULT_PIN, PIN_PREFIX } from '../LocalDatastoreUtils'; +import { DEFAULT_PIN, PIN_PREFIX } from "../LocalDatastoreUtils"; const mockLocalDatastore = { isEnabled: false, @@ -136,979 +138,1003 @@ const mockLocalDatastore = { getKeyForObject: jest.fn(), checkIfEnabled: jest.fn(() => { if (!mockLocalDatastore.isEnabled) { - console.error('Parse.enableLocalDatastore() must be called first'); + console.error("Parse.enableLocalDatastore() must be called first"); } return mockLocalDatastore.isEnabled; }), }; -jest.setMock('../LocalDatastore', mockLocalDatastore); - -const CoreManager = require('../CoreManager'); -const ParseACL = require('../ParseACL').default; -const ParseError = require('../ParseError').default; -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParsePolygon = require('../ParsePolygon').default; -const ParseObject = require('../ParseObject').default; -const ParseOp = require('../ParseOp'); -const RESTController = require('../RESTController'); -const SingleInstanceStateController = require('../SingleInstanceStateController'); -const unsavedChildren = require('../unsavedChildren').default; - -const mockXHR = require('./test_helpers/mockXHR'); +jest.setMock("../LocalDatastore", mockLocalDatastore); + +const CoreManager = require("../CoreManager"); +const ParseACL = require("../ParseACL").default; +const ParseError = require("../ParseError").default; +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParsePolygon = require("../ParsePolygon").default; +const ParseObject = require("../ParseObject").default; +const ParseOp = require("../ParseOp"); +const RESTController = require("../RESTController"); +const SingleInstanceStateController = require("../SingleInstanceStateController"); +const unsavedChildren = require("../unsavedChildren").default; + +const mockXHR = require("./test_helpers/mockXHR"); CoreManager.setLocalDatastore(mockLocalDatastore); CoreManager.setRESTController(RESTController); CoreManager.setInstallationController({ currentInstallationId() { - return Promise.resolve('iid'); - } + return Promise.resolve("iid"); + }, }); -CoreManager.set('APPLICATION_ID', 'A'); -CoreManager.set('JAVASCRIPT_KEY', 'B'); -CoreManager.set('MASTER_KEY', 'C'); -CoreManager.set('VERSION', 'V'); +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)); + return new Promise((resolve) => setImmediate(resolve)); } -describe('ParseObject', () => { +describe("ParseObject", () => { beforeEach(() => { ParseObject.enableSingleInstance(); jest.clearAllMocks(); }); - it('is initially created with no Id', () => { - const o = new ParseObject('Item'); + it("is initially created with no Id", () => { + const o = new ParseObject("Item"); expect(o.id).toBe(undefined); expect(o._localId).toBe(undefined); expect(o.dirty()).toBe(true); }); - it('can be created with initial attributes', () => { + it("can be created with initial attributes", () => { const o = new ParseObject({ - className: 'Item', - value: 12 + className: "Item", + value: 12, }); - expect(o.className).toBe('Item'); + expect(o.className).toBe("Item"); expect(o.attributes).toEqual({ value: 12 }); }); - it('can be created with attributes parameter', () => { - const o = new ParseObject('Item', { + it("can be created with attributes parameter", () => { + const o = new ParseObject("Item", { value: 12, }); - expect(o.className).toBe('Item'); + expect(o.className).toBe("Item"); expect(o.attributes).toEqual({ value: 12 }); }); - it('can ignore setting invalid key', () => { - const o = new ParseObject('Item'); + it("can ignore setting invalid key", () => { + const o = new ParseObject("Item"); const o2 = o.set(1234); expect(o).toEqual(o2); }); - it('can ignore setting createdAt', () => { - const o = new ParseObject('Item'); - o.set('createdAt', '1234'); - expect(o.get('createdAt')).toEqual(undefined); + it("can ignore setting createdAt", () => { + const o = new ParseObject("Item"); + o.set("createdAt", "1234"); + expect(o.get("createdAt")).toEqual(undefined); }); - it('can handle setting relationOp', () => { - const child = new ParseObject('Child'); - child.id = 'child1234'; - const relationOpJSON = { __op: 'AddRelation', objects: [child] }; - const o = new ParseObject('Item'); - o.set('friends', relationOpJSON); + it("can handle setting relationOp", () => { + const child = new ParseObject("Child"); + child.id = "child1234"; + const relationOpJSON = { __op: "AddRelation", objects: [child] }; + const o = new ParseObject("Item"); + o.set("friends", relationOpJSON); o._handleSaveResponse({}); - expect(o.get('friends').targetClassName).toBe('Child'); + expect(o.get("friends").targetClassName).toBe("Child"); }); - it('cannot create with invalid attributes', () => { + it("cannot create with invalid attributes", () => { expect(() => { new ParseObject({ - className: 'Item', - 'invalid#name' : 'foo', + className: "Item", + "invalid#name": "foo", }); }).toThrow("Can't create an invalid Parse Object"); }); - it('can ignore validation if ignoreValidation option is provided', () => { + it("can ignore validation if ignoreValidation option is provided", () => { class ValidatedObject extends ParseObject { validate(attrs) { - if (attrs.hasOwnProperty('badAttr')) { - return 'you have the bad attr'; + if (attrs.hasOwnProperty("badAttr")) { + return "you have the bad attr"; } } } - 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); }); - it('can be inflated from server JSON', () => { + it("can be inflated from server JSON", () => { const json = { - className: 'Item', - createdAt: '2013-12-14T04:51:19Z', - objectId: 'I1', - size: 'medium' + className: "Item", + createdAt: "2013-12-14T04:51:19Z", + objectId: "I1", + size: "medium", }; const o = ParseObject.fromJSON(json); - expect(o.className).toBe('Item'); - expect(o.id).toBe('I1'); + expect(o.className).toBe("Item"); + expect(o.id).toBe("I1"); expect(o.attributes).toEqual({ - size: 'medium', + 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); }); - it('can override old data when inflating from the server', () => { + it("can override old data when inflating from the server", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'I01', - size: 'small' - }); - expect(o.get('size')).toBe('small'); - 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); - - expect(o2.get('disabled')).toBe(true); - expect(o2.get('size')).toBe(undefined); - expect(o2.has('size')).toBe(false); - }); - - it('is given a local Id once dirtied', () => { - const o = new ParseObject('Item'); - o.set('size', 'small'); + className: "Item", + objectId: "I01", + size: "small", + }); + expect(o.get("size")).toBe("small"); + 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); + + expect(o2.get("disabled")).toBe(true); + expect(o2.get("size")).toBe(undefined); + expect(o2.has("size")).toBe(false); + }); + + it("is given a local Id once dirtied", () => { + const o = new ParseObject("Item"); + o.set("size", "small"); expect(o._localId).toBeTruthy(); }); - it('has a read-only attributes property', () => { - const o = new ParseObject('Item'); - o.set('size', 'small'); - expect(function() { o.attributes.size = 'large'; }).toThrow(); + it("has a read-only attributes property", () => { + const o = new ParseObject("Item"); + o.set("size", "small"); + expect(function () { + o.attributes.size = "large"; + }).toThrow(); }); - it('exposes read-only createdAt and updatedAt', () => { - const o = new ParseObject('Item'); - expect(o.get('createdAt')).toBe(undefined); - expect(o.get('updatedAt')).toBe(undefined); + it("exposes read-only createdAt and updatedAt", () => { + const o = new ParseObject("Item"); + expect(o.get("createdAt")).toBe(undefined); + expect(o.get("updatedAt")).toBe(undefined); const created = new Date(); const updated = new Date(); o._finishFetch({ - objectId: 'O1', - createdAt: { __type: 'Date', iso: created.toISOString() }, - updatedAt: { __type: 'Date', iso: updated.toISOString() } + objectId: "O1", + createdAt: { __type: "Date", iso: created.toISOString() }, + updatedAt: { __type: "Date", iso: updated.toISOString() }, }); - expect(o.get('createdAt')).toEqual(created); - expect(o.get('updatedAt')).toEqual(updated); + expect(o.get("createdAt")).toEqual(created); + expect(o.get("updatedAt")).toEqual(updated); expect(o.createdAt).toEqual(created); expect(o.updatedAt).toEqual(updated); }); - it('fetch ACL from serverData', () => { - const ACL = new ParseACL({ 'user1': { read: true } }); - const o = new ParseObject('Item'); + it("fetch ACL from serverData", () => { + const ACL = new ParseACL({ user1: { read: true } }); + const o = new ParseObject("Item"); o._finishFetch({ - objectId: 'O1', - ACL: { 'user1': { read: true } }, + objectId: "O1", + ACL: { user1: { read: true } }, }); expect(o.getACL()).toEqual(ACL); }); - it('can be rendered to JSON', () => { - let o = new ParseObject('Item'); + it("can be rendered to JSON", () => { + let o = new ParseObject("Item"); o.set({ - size: 'large', - inStock: 18 + size: "large", + inStock: 18, }); expect(o.toJSON()).toEqual({ - size: 'large', - inStock: 18 + size: "large", + inStock: 18, }); - o = new ParseObject('Item'); + o = new ParseObject("Item"); o._finishFetch({ - objectId: 'O2', - size: 'medium', - inStock: 12 + objectId: "O2", + size: "medium", + inStock: 12, }); - expect(o.id).toBe('O2'); + expect(o.id).toBe("O2"); expect(o.toJSON()).toEqual({ - objectId: 'O2', - size: 'medium', - inStock: 12 + objectId: "O2", + size: "medium", + inStock: 12, }); }); - it('encodes createdAt and updatedAt fields as strings', () => { + it("encodes createdAt and updatedAt fields as strings", () => { 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' + 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", }); expect(o.toJSON()).toEqual({ - id: 'hasDates', - createdAt: '2015-01-01T00:00:00.000Z', - updatedAt: '2015-01-01T00:00:00.000Z', - foo: 'bar' + id: "hasDates", + createdAt: "2015-01-01T00:00:00.000Z", + updatedAt: "2015-01-01T00:00:00.000Z", + 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' - ); - o.id = 'anObjectId'; + it("can convert to a pointer", () => { + const o = new ParseObject("Item"); + 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' + __type: "Pointer", + className: "Item", + 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' - ); - o._localId = 'local1234'; + 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"); + o._localId = "local1234"; expect(o.toOfflinePointer()).toEqual({ - __type: 'Object', - className: 'Item', - _localId: 'local1234' + __type: "Object", + className: "Item", + _localId: "local1234", }); }); - it('can test equality against another ParseObject', () => { - const a = new ParseObject('Item'); + it("can test equality against another ParseObject", () => { + const a = new ParseObject("Item"); expect(a.equals(a)).toBe(true); - const b = new ParseObject('Item'); + const b = new ParseObject("Item"); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); - a.id = 'anObjectId'; - b.id = 'anObjectId'; + a.id = "anObjectId"; + b.id = "anObjectId"; expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); }); - it('can set a field', () => { - const o = new ParseObject('Person'); + it("can set a field", () => { + const o = new ParseObject("Person"); expect(o.attributes).toEqual({}); - o.set('name', 'Will'); - expect(o.attributes).toEqual({ name: 'Will' }); - expect(o.op('name') instanceof SetOp).toBe(true); - expect(o.dirtyKeys()).toEqual(['name']); + o.set("name", "Will"); + expect(o.attributes).toEqual({ name: "Will" }); + expect(o.op("name") instanceof SetOp).toBe(true); + expect(o.dirtyKeys()).toEqual(["name"]); expect(o.dirty()).toBe(true); - expect(o.dirty('name')).toBe(true); - expect(o._getSaveJSON()).toEqual({ name: 'Will' }); + expect(o.dirty("name")).toBe(true); + expect(o._getSaveJSON()).toEqual({ name: "Will" }); // set multiple fields at once - o.set({ name: 'William', behavior: 'formal' }); - expect(o.attributes).toEqual({ name: 'William', behavior: 'formal' }); + o.set({ name: "William", behavior: "formal" }); + expect(o.attributes).toEqual({ name: "William", behavior: "formal" }); }); - it('can set id with the objectId attribute', () => { - const o = new ParseObject('Person'); + it("can set id with the objectId attribute", () => { + const o = new ParseObject("Person"); expect(o.attributes).toEqual({}); expect(o.id).toBe(undefined); - o.set({ objectId: 'oid' }); + o.set({ objectId: "oid" }); expect(o.attributes).toEqual({}); - expect(o.id).toBe('oid'); + expect(o.id).toBe("oid"); }); - it('can get an escaped version of a field', () => { - const o = new ParseObject('Person'); - o.set('age', 28); - o.set('phoneProvider', 'AT&T'); - o.set('objectField', { toString: 'hacking' }); - expect(o.escape('notSet')).toBe(''); - expect(o.escape('age')).toBe('28'); - expect(o.escape('phoneProvider')).toBe('AT&T'); - expect(o.escape('objectField')).toBe(''); + it("can get an escaped version of a field", () => { + const o = new ParseObject("Person"); + o.set("age", 28); + o.set("phoneProvider", "AT&T"); + o.set("objectField", { toString: "hacking" }); + expect(o.escape("notSet")).toBe(""); + expect(o.escape("age")).toBe("28"); + expect(o.escape("phoneProvider")).toBe("AT&T"); + expect(o.escape("objectField")).toBe(""); }); - it('can tell if it has an attribute', () => { - const o = new ParseObject('Person'); - o.set('age', 28); - expect(o.has('name')).toBe(false); - expect(o.has('age')).toBe(true); + it("can tell if it has an attribute", () => { + const o = new ParseObject("Person"); + o.set("age", 28); + expect(o.has("name")).toBe(false); + expect(o.has("age")).toBe(true); }); - it('can tell if a field is dirty', () => { - const o = new ParseObject('Person'); + it("can tell if a field is dirty", () => { + const o = new ParseObject("Person"); o._finishFetch({ - objectId: 'p99', + objectId: "p99", age: 28, human: true, - objectField: { foo: 'bar' }, + objectField: { foo: "bar" }, }); expect(o.dirty()).toBe(false); - expect(o.dirty('age')).toBe(false); - expect(o.dirty('human')).toBe(false); - expect(o.dirty('unset')).toBe(false); - expect(o.dirty('objectField')).toBe(false); - o.set('human', false); - o.set('objectField', { foo: 'baz' }); + expect(o.dirty("age")).toBe(false); + expect(o.dirty("human")).toBe(false); + expect(o.dirty("unset")).toBe(false); + expect(o.dirty("objectField")).toBe(false); + o.set("human", false); + o.set("objectField", { foo: "baz" }); expect(o.dirty()).toBe(true); - expect(o.dirty('age')).toBe(false); - 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'); - o.id = 'anObjectId'; - o.set('name', 'Will'); - expect(o.attributes).toEqual({ name: 'Will' }); - o.unset('name'); + expect(o.dirty("age")).toBe(false); + 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"); + o.id = "anObjectId"; + o.set("name", "Will"); + expect(o.attributes).toEqual({ name: "Will" }); + o.unset("name"); expect(o.attributes).toEqual({}); // Even when you unset an unsaved set, it's still dirty - expect(o.op('name') instanceof UnsetOp).toBe(true); + expect(o.op("name") instanceof UnsetOp).toBe(true); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual(['name']); + expect(o.dirtyKeys()).toEqual(["name"]); - const o2 = new ParseObject('Person'); + const o2 = new ParseObject("Person"); o2._finishFetch({ - objectId: 'P1', - name: 'Will' + objectId: "P1", + name: "Will", }); - expect(o2.attributes).toEqual({ name: 'Will' }); - o2.unset('name'); + expect(o2.attributes).toEqual({ name: "Will" }); + o2.unset("name"); expect(o2.attributes).toEqual({}); }); - it('can clear all fields', () => { - const o = new ParseObject('Person'); + it("can clear all fields", () => { + const o = new ParseObject("Person"); o._finishFetch({ - objectId: 'P95', - createdAt: { __type: 'Date', iso: new Date().toISOString() }, - updatedAt: { __type: 'Date', iso: new Date().toISOString() }, - }); - o.set({ a: 'a', b: 'b', c: 'c' }); - expect(o.dirty('a')).toBe(true); - expect(o.dirty('b')).toBe(true); - expect(o.dirty('c')).toBe(true); + objectId: "P95", + createdAt: { __type: "Date", iso: new Date().toISOString() }, + updatedAt: { __type: "Date", iso: new Date().toISOString() }, + }); + o.set({ a: "a", b: "b", c: "c" }); + expect(o.dirty("a")).toBe(true); + expect(o.dirty("b")).toBe(true); + expect(o.dirty("c")).toBe(true); o.clear(); - expect(o.get('a')).toBe(undefined); - expect(o.get('b')).toBe(undefined); - expect(o.get('c')).toBe(undefined); + expect(o.get("a")).toBe(undefined); + expect(o.get("b")).toBe(undefined); + expect(o.get("c")).toBe(undefined); }); - it('can increment a field', () => { - const o = new ParseObject('Person'); - o.increment('age'); + it("can increment a field", () => { + const o = new ParseObject("Person"); + o.increment("age"); expect(o.attributes).toEqual({ age: 1 }); - expect(o.op('age') instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(['age']); + 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); + 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", "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", 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.' + expect(o.increment.bind(o, "age", { amount: 4 })).toThrow( + "Cannot increment by a non-numeric amount." ); - o.set('age', 30); - o.increment('age'); + o.set("age", 30); + o.increment("age"); expect(o.attributes).toEqual({ age: 31 }); expect(o._getSaveJSON()).toEqual({ - age: 31 + age: 31, }); - const o2 = new ParseObject('Person'); + const o2 = new ParseObject("Person"); o2._finishFetch({ - objectId: 'P2', - age: 40 + objectId: "P2", + age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); - o2.increment('age'); + o2.increment("age"); expect(o2.attributes).toEqual({ age: 41 }); }); - - it('can decrement a field', () => { - const o = new ParseObject('Person'); - o.decrement('age'); + it("can decrement a field", () => { + const o = new ParseObject("Person"); + o.decrement("age"); expect(o.attributes).toEqual({ age: -1 }); - expect(o.op('age') instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(['age']); + 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); + 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", "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", 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.' + expect(o.decrement.bind(o, "age", { amount: 4 })).toThrow( + "Cannot decrement by a non-numeric amount." ); - o.set('age', 30); - o.decrement('age'); + o.set("age", 30); + o.decrement("age"); expect(o.attributes).toEqual({ age: 29 }); expect(o._getSaveJSON()).toEqual({ - age: 29 + age: 29, }); - const o2 = new ParseObject('Person'); + const o2 = new ParseObject("Person"); o2._finishFetch({ - objectId: 'ABC123', - age: 40 + objectId: "ABC123", + age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); - o2.decrement('age'); + o2.decrement("age"); expect(o2.attributes).toEqual({ age: 39 }); }); - it('can set nested field', () => { - const o = new ParseObject('Person'); + it("can set nested field", () => { + const o = new ParseObject("Person"); o._finishFetch({ - objectId: 'setNested', + objectId: "setNested", objectField: { number: 5, - letter: 'a' + letter: "a", }, otherField: {}, }); expect(o.attributes).toEqual({ - objectField: { number: 5, letter: 'a' }, + objectField: { number: 5, letter: "a" }, otherField: {}, }); - o.set('otherField', { hello: 'world' }); - o.set('objectField.number', 20); + o.set("otherField", { hello: "world" }); + o.set("objectField.number", 20); expect(o.attributes).toEqual({ - objectField: { number: 20, letter: 'a' }, - otherField: { hello: 'world' }, - }); - expect(o.op('objectField.number') instanceof SetOp).toBe(true); - expect(o.dirtyKeys()).toEqual(['otherField', 'objectField.number', 'objectField']); + objectField: { number: 20, letter: "a" }, + otherField: { hello: "world" }, + }); + expect(o.op("objectField.number") instanceof SetOp).toBe(true); + expect(o.dirtyKeys()).toEqual([ + "otherField", + "objectField.number", + "objectField", + ]); expect(o._getSaveJSON()).toEqual({ - 'objectField.number': 20, - otherField: { hello: 'world' }, + "objectField.number": 20, + otherField: { hello: "world" }, }); }); - it('can increment a nested field', () => { - const o = new ParseObject('Person'); + it("can increment a nested field", () => { + const o = new ParseObject("Person"); o._finishFetch({ - objectId: 'incNested', + objectId: "incNested", objectField: { number: 5, - letter: 'a' + letter: "a", }, }); expect(o.attributes).toEqual({ - objectField: { number: 5, letter: 'a' }, + objectField: { number: 5, letter: "a" }, }); - o.increment('objectField.number'); + o.increment("objectField.number"); expect(o.attributes).toEqual({ - objectField: { number: 6, letter: 'a' }, + objectField: { number: 6, letter: "a" }, }); - expect(o.op('objectField.number') instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(['objectField.number', 'objectField']); + expect(o.op("objectField.number") instanceof IncrementOp).toBe(true); + expect(o.dirtyKeys()).toEqual(["objectField.number", "objectField"]); expect(o._getSaveJSON()).toEqual({ - 'objectField.number': { - "__op": "Increment", - "amount": 1 + "objectField.number": { + __op: "Increment", + amount: 1, }, }); // Nested objects only return values changed o._handleSaveResponse({ - objectId: 'incNested', + 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', () => { - const o = new ParseObject('Person'); - o.set('objectField.number', 20); + it("ignore set nested field on new object", () => { + const o = new ParseObject("Person"); + o.set("objectField.number", 20); expect(o.attributes).toEqual({}); - expect(o.op('objectField.number') instanceof SetOp).toBe(false); + expect(o.op("objectField.number") instanceof SetOp).toBe(false); expect(o.dirtyKeys()).toEqual([]); expect(o._getSaveJSON()).toEqual({}); }); - it('can add elements to an array field', () => { - const o = new ParseObject('Schedule'); - o.add('available', 'Monday'); - o.add('available', 'Wednesday'); - expect(o.get('available')).toEqual(['Monday', 'Wednesday']); + it("can add elements to an array field", () => { + const o = new ParseObject("Schedule"); + o.add("available", "Monday"); + o.add("available", "Wednesday"); + expect(o.get("available")).toEqual(["Monday", "Wednesday"]); - o.set('colors', ['red', 'green']); - o.add('colors', 'blue'); - expect(o.get('colors')).toEqual(['red', 'green', 'blue']); + o.set("colors", ["red", "green"]); + o.add("colors", "blue"); + expect(o.get("colors")).toEqual(["red", "green", "blue"]); o._handleSaveResponse({ - objectId: 'S1', - available: ['Monday', 'Wednesday'], - colors: ['red', 'green', 'blue'] + objectId: "S1", + available: ["Monday", "Wednesday"], + colors: ["red", "green", "blue"], }); - o.addUnique('available', 'Thursday'); - o.addUnique('available', 'Monday'); - expect(o.get('available')).toEqual(['Monday', 'Wednesday', 'Thursday']); + o.addUnique("available", "Thursday"); + o.addUnique("available", "Monday"); + expect(o.get("available")).toEqual(["Monday", "Wednesday", "Thursday"]); }); - it('can add elements to an array field in batch mode', () => { - const o = new ParseObject('Schedule'); - o.addAll('available', ['Monday', 'Wednesday']); - expect(o.get('available')).toEqual(['Monday', 'Wednesday']); + it("can add elements to an array field in batch mode", () => { + const o = new ParseObject("Schedule"); + o.addAll("available", ["Monday", "Wednesday"]); + expect(o.get("available")).toEqual(["Monday", "Wednesday"]); - o.set('colors', ['red']); - o.addAll('colors', ['green', 'blue']); - expect(o.get('colors')).toEqual(['red', 'green', 'blue']); + o.set("colors", ["red"]); + o.addAll("colors", ["green", "blue"]); + expect(o.get("colors")).toEqual(["red", "green", "blue"]); o._handleSaveResponse({ - objectId: 'S1', - available: ['Monday', 'Wednesday'], - colors: ['red', 'green', 'blue'] + objectId: "S1", + available: ["Monday", "Wednesday"], + colors: ["red", "green", "blue"], }); - o.addAllUnique('available', ['Thursday', 'Monday']); - expect(o.get('available').length).toEqual(3); + o.addAllUnique("available", ["Thursday", "Monday"]); + expect(o.get("available").length).toEqual(3); }); - it('can remove elements from an array field', () => { - const o = new ParseObject('Schedule'); - o.set('available', ['Monday', 'Tuesday']); - o.remove('available', 'Tuesday'); - o.remove('available', 'Saturday'); - expect(o.get('available')).toEqual(['Monday']); + it("can remove elements from an array field", () => { + const o = new ParseObject("Schedule"); + o.set("available", ["Monday", "Tuesday"]); + o.remove("available", "Tuesday"); + o.remove("available", "Saturday"); + expect(o.get("available")).toEqual(["Monday"]); o._handleSaveResponse({ - objectId: 'S2', - available: ['Monday'] + objectId: "S2", + available: ["Monday"], }); - o.remove('available', 'Monday'); - o.remove('available', 'Tuesday'); - expect(o.get('available')).toEqual([]); + o.remove("available", "Monday"); + o.remove("available", "Tuesday"); + expect(o.get("available")).toEqual([]); }); - it('can remove elements from an array field in batch mode', () => { - const o = new ParseObject('Schedule'); - o.set('available', ['Monday', 'Tuesday']); - o.removeAll('available', ['Tuesday', 'Saturday']); - expect(o.get('available')).toEqual(['Monday']); + it("can remove elements from an array field in batch mode", () => { + const o = new ParseObject("Schedule"); + o.set("available", ["Monday", "Tuesday"]); + o.removeAll("available", ["Tuesday", "Saturday"]); + expect(o.get("available")).toEqual(["Monday"]); o._handleSaveResponse({ - objectId: 'S2', - available: ['Monday'] + objectId: "S2", + available: ["Monday"], }); - o.removeAll('available', ['Monday', 'Tuesday']); - expect(o.get('available')).toEqual([]); + o.removeAll("available", ["Monday", "Tuesday"]); + expect(o.get("available")).toEqual([]); }); - it('can chain sets', () => { - const o = new ParseObject('Person'); - o.set('developer', true).set('platform', 'web'); + it("can chain sets", () => { + const o = new ParseObject("Person"); + o.set("developer", true).set("platform", "web"); expect(o.attributes).toEqual({ developer: true, - platform: 'web' + platform: "web", }); }); - it('can set and retrieve ACLs', () => { + it("can set and retrieve ACLs", () => { const acl = new ParseACL(); - const o = new ParseObject('Listing'); + const o = new ParseObject("Listing"); o.setACL(acl); - expect(o.get('ACL')).toBe(acl); + expect(o.get("ACL")).toBe(acl); expect(o.getACL()).toBe(acl); }); - it('can manipulate relations on fields', () => { - 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' + it("can manipulate relations on fields", () => { + 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" ); - const rel = o.relation('friends'); - expect(rel.parentClass).toBe('Person'); - expect(rel.parentId).toBe('AA'); - expect(rel.key).toBe('friends'); - const friend = new ParseObject('Person'); - friend.id = 'BB'; + const rel = o.relation("friends"); + expect(rel.parentClass).toBe("Person"); + expect(rel.parentId).toBe("AA"); + expect(rel.key).toBe("friends"); + const friend = new ParseObject("Person"); + friend.id = "BB"; rel.add(friend); - expect(rel.targetClassName).toBe('Person'); + expect(rel.targetClassName).toBe("Person"); }); - it('can be cloned with relation (#381)', () => { - const relationJSON = {__type: 'Relation', className: 'Bar'}; + it("can be cloned with relation (#381)", () => { + const relationJSON = { __type: "Relation", className: "Bar" }; const o = ParseObject.fromJSON({ - objectId: '7777777777', - className: 'Foo', + objectId: "7777777777", + className: "Foo", aRelation: relationJSON, }); const o2 = o.clone(); expect(o2._getSaveJSON().aRelation).toEqual(relationJSON); }); - it('can get relation from relation field', () => { - const relationJSON = {__type: 'Relation', className: 'Bar'}; + it("can get relation from relation field", () => { + const relationJSON = { __type: "Relation", className: "Bar" }; const o = ParseObject.fromJSON({ - objectId: '999', - className: 'Foo', + objectId: "999", + className: "Foo", aRelation: relationJSON, }); - const rel = o.relation('aRelation'); + const rel = o.relation("aRelation"); expect(rel.toJSON()).toEqual(relationJSON); }); - it('can detect dirty object children', () => { - const o = new ParseObject('Person'); + it("can detect dirty object children", () => { + const o = new ParseObject("Person"); o._finishFetch({ - objectId: 'dirtyObj', + objectId: "dirtyObj", obj: { a: 12 }, location: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 20, - longitude: 20 - } + longitude: 20, + }, }); expect(o.dirty()).toBe(false); - o.get('obj').b = 21; - expect(o.get('obj')).toEqual({ + 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.dirtyKeys()).toEqual(["obj"]); expect(o._getSaveJSON()).toEqual({ obj: { a: 12, - b: 21 - } + b: 21, + }, }); - delete o.get('obj').b; + delete o.get("obj").b; expect(o.dirty()).toBe(false); expect(o.dirtyKeys()).toEqual([]); - const loc = o.get('location'); + const loc = o.get("location"); expect(loc instanceof ParseGeoPoint).toBe(true); expect(loc.latitude).toBe(20); expect(loc.longitude).toBe(20); loc.latitude = 30; expect(loc.latitude).toBe(30); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual(['location']); + expect(o.dirtyKeys()).toEqual(["location"]); - const p = new ParseObject('Parent'); - p.set('children', [o]); - expect(p.dirtyKeys()).toEqual(['children']); + const p = new ParseObject("Parent"); + p.set("children", [o]); + expect(p.dirtyKeys()).toEqual(["children"]); }); - 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.') + 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({ - '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()', () => { - const o = new ParseObject('Listing'); - expect(o.set('ACL', 'not an acl')).toBe(false); - expect(o.set('ACL', { '*': { read: true, write: false } })).toBe(o); - expect(o.set('$$$', 'o_O')).toBe(false); + it("validates attributes on set()", () => { + const o = new ParseObject("Listing"); + expect(o.set("ACL", "not an acl")).toBe(false); + 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()', () => { - const o = new ParseObject('Listing'); - expect(o.set('$$$', 'o_O', { ignoreValidation: true })).toBe(o); + it("ignores validation if ignoreValidation option is passed to set()", () => { + const o = new ParseObject("Listing"); + expect(o.set("$$$", "o_O", { ignoreValidation: true })).toBe(o); }); - it('can test object validity', () => { + it("can test object validity", () => { // Note: an object should never become invalid through normal use, but // it's possible that someone could manipulate it to become invalid - const o = new ParseObject('Item'); + const o = new ParseObject("Item"); expect(o.isValid()).toBe(true); - o.set('someKey', 'someValue'); + o.set("someKey", "someValue"); expect(o.isValid()).toBe(true); o._finishFetch({ - objectId: 'O3', - 'invalid!key': 'oops' + objectId: "O3", + "invalid!key": "oops", }); expect(o.isValid()).toBe(false); }); - it('shares data among different instances of an object', () => { - const o = new ParseObject('Person'); - o.id = 'P2'; - const o2 = new ParseObject('Person'); - o2.id = 'P2'; - o.set('age', 22); - expect(o.get('age')).toBe(22); - expect(o2.get('age')).toBe(22); + it("shares data among different instances of an object", () => { + const o = new ParseObject("Person"); + o.id = "P2"; + const o2 = new ParseObject("Person"); + o2.id = "P2"; + o.set("age", 22); + expect(o.get("age")).toBe(22); + expect(o2.get("age")).toBe(22); }); - it('does not stack-overflow when encoding recursive pointers', () => { + it("does not stack-overflow when encoding recursive pointers", () => { const o = ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'recurParent', + __type: "Object", + className: "Item", + objectId: "recurParent", child: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurChild' - } + __type: "Pointer", + className: "Item", + objectId: "recurChild", + }, }); expect(o.toJSON()).toEqual({ - objectId: 'recurParent', + objectId: "recurParent", child: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurChild' - } + __type: "Pointer", + className: "Item", + objectId: "recurChild", + }, }); ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'recurChild', + __type: "Object", + className: "Item", + objectId: "recurChild", parent: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurParent' - } + __type: "Pointer", + className: "Item", + objectId: "recurParent", + }, }); expect(o.toJSON()).toEqual({ - objectId: 'recurParent', + objectId: "recurParent", child: { - __type: 'Object', - className: 'Item', - objectId: 'recurChild', + __type: "Object", + className: "Item", + objectId: "recurChild", parent: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurParent' - } - } + __type: "Pointer", + className: "Item", + objectId: "recurParent", + }, + }, }); }); - it('properly encodes createdAt/updatedAt dates on nested objects', () => { + it("properly encodes createdAt/updatedAt dates on nested objects", () => { const o = ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'recurParent', - createdAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z', + __type: "Object", + className: "Item", + objectId: "recurParent", + createdAt: "1970-01-01T00:00:00.000Z", + updatedAt: "1970-01-01T00:00:00.000Z", aDate: { - __type: 'Date', - iso: '1970-01-01T00:00:00.000Z' + __type: "Date", + iso: "1970-01-01T00:00:00.000Z", }, child: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurChild' - } + __type: "Pointer", + className: "Item", + objectId: "recurChild", + }, }); expect(o.createdAt.getTime()).toBe(new Date(0).getTime()); expect(o.updatedAt.getTime()).toBe(new Date(0).getTime()); - expect(o.get('aDate').getTime()).toBe(new Date(0).getTime()); + expect(o.get("aDate").getTime()).toBe(new Date(0).getTime()); ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'recurChild', - createdAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z', + __type: "Object", + className: "Item", + objectId: "recurChild", + createdAt: "1970-01-01T00:00:00.000Z", + updatedAt: "1970-01-01T00:00:00.000Z", parent: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurParent' - } + __type: "Pointer", + className: "Item", + objectId: "recurParent", + }, }); expect(o.toJSON()).toEqual({ - objectId: 'recurParent', - createdAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z', + objectId: "recurParent", + createdAt: "1970-01-01T00:00:00.000Z", + updatedAt: "1970-01-01T00:00:00.000Z", aDate: { - __type: 'Date', - iso: '1970-01-01T00:00:00.000Z' + __type: "Date", + iso: "1970-01-01T00:00:00.000Z", }, child: { - __type: 'Object', - className: 'Item', - objectId: 'recurChild', - createdAt: '1970-01-01T00:00:00.000Z', - updatedAt: '1970-01-01T00:00:00.000Z', + __type: "Object", + className: "Item", + objectId: "recurChild", + createdAt: "1970-01-01T00:00:00.000Z", + updatedAt: "1970-01-01T00:00:00.000Z", parent: { - __type: 'Pointer', - className: 'Item', - objectId: 'recurParent' - } - } + __type: "Pointer", + className: "Item", + objectId: "recurParent", + }, + }, }); }); - it('encodes multiple layers of nested objects', () => { + it("encodes multiple layers of nested objects", () => { const grandparent = ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'nestedGrand', + __type: "Object", + className: "Item", + objectId: "nestedGrand", child: { - __type: 'Pointer', - className: 'Item', - objectId: 'nestedParent' - } + __type: "Pointer", + className: "Item", + objectId: "nestedParent", + }, }); const parent = ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'nestedParent', + __type: "Object", + className: "Item", + objectId: "nestedParent", child: { - __type: 'Pointer', - className: 'Item', - objectId: 'nestedChild' - } + __type: "Pointer", + className: "Item", + objectId: "nestedChild", + }, }); const child = ParseObject.fromJSON({ - __type: 'Object', - className: 'Item', - objectId: 'nestedChild', - count: 12 + __type: "Object", + className: "Item", + objectId: "nestedChild", + count: 12, }); - expect(grandparent.get('child').id).toBe(parent.id); - expect(grandparent.get('child').get('child').id).toBe(child.id); + expect(grandparent.get("child").id).toBe(parent.id); + expect(grandparent.get("child").get("child").id).toBe(child.id); expect(grandparent.toJSON()).toEqual({ - objectId: 'nestedGrand', + objectId: "nestedGrand", child: { - __type: 'Object', - className: 'Item', - objectId: 'nestedParent', + __type: "Object", + className: "Item", + objectId: "nestedParent", child: { - __type: 'Object', - className: 'Item', - objectId: 'nestedChild', - count: 12 - } - } + __type: "Object", + className: "Item", + objectId: "nestedChild", + count: 12, + }, + }, }); }); - it('updates the existed flag when saved', () => { - const o = new ParseObject('Item'); + it("updates the existed flag when saved", () => { + 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); }); - it('check existed without object state', () => { - const o = new ParseObject('Item'); - o.id = 'test890'; + it("check existed without object state", () => { + const o = new ParseObject("Item"); + o.id = "test890"; expect(o.existed()).toBe(false); }); - it('commits changes to server data when saved', () => { - const p = new ParseObject('Person'); - p.id = 'P3'; - p.set('age', 24); + it("commits changes to server data when saved", () => { + const p = new ParseObject("Person"); + p.id = "P3"; + p.set("age", 24); expect(p._getServerData()).toEqual({}); - expect(p.op('age') instanceof SetOp).toBe(true); + 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); + expect(p.op("age")).toBe(undefined); }); - it('handle GeoPoint changes for server', () => { - const p = new ParseObject('Person'); - p.id = 'PPoint'; + it("handle GeoPoint changes for server", () => { + const p = new ParseObject("Person"); + p.id = "PPoint"; const created = new Date(); const geopoint = new ParseGeoPoint(0, 0); p._handleSaveResponse({ @@ -1123,11 +1149,17 @@ describe('ParseObject', () => { expect(p._getServerData().point instanceof ParseGeoPoint).toBe(true); }); - it('handle Polygon changes for server', () => { - const p = new ParseObject('Person'); - p.id = 'PPolygon'; + it("handle Polygon changes for server", () => { + 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(), @@ -1140,12 +1172,12 @@ describe('ParseObject', () => { expect(p._getServerData().shape instanceof ParsePolygon).toBe(true); }); - it('handle createdAt string for server', () => { - const p = new ParseObject('Person'); - p.id = 'P9'; + it("handle createdAt string for server", () => { + const p = new ParseObject("Person"); + p.id = "P9"; const created = new Date(); p._handleSaveResponse({ - createdAt: created.toISOString() + createdAt: created.toISOString(), }); expect(p._getServerData()).toEqual({ updatedAt: created, @@ -1153,331 +1185,366 @@ describe('ParseObject', () => { }); }); - it('isDataAvailable', () => { - const p = new ParseObject('Person'); - p.id = 'isdataavailable'; - p.set('age', 24); + it("isDataAvailable", () => { + const p = new ParseObject("Person"); + p.id = "isdataavailable"; + p.set("age", 24); 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); }); - it('handles ACL when saved', () => { - const p = new ParseObject('Person'); + 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); expect(acl instanceof ParseACL).toBe(true); }); - it('replaces a local id with a real one when saved', () => { - const p = new ParseObject('Person'); - p.set('age', 34); + it("replaces a local id with a real one when saved", () => { + const p = new ParseObject("Person"); + 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' }); + expect(p.id).toBe("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); }); - it('marks inflated objects as existed', () => { + it("marks inflated objects as existed", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'iexist', - count: 7 + className: "Item", + objectId: "iexist", + count: 7, }); expect(o.existed()).toBe(true); }); - it('can revert unsaved ops', () => { + it("can revert unsaved ops", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'canrevert', - count: 5 + className: "Item", + objectId: "canrevert", + count: 5, }); o.set({ cool: true }); - o.increment('count'); - expect(o.get('cool')).toBe(true); - expect(o.get('count')).toBe(6); + o.increment("count"); + expect(o.get("cool")).toBe(true); + expect(o.get("count")).toBe(6); o.revert(); - expect(o.get('cool')).toBe(undefined); - expect(o.op('cool')).toBe(undefined); - expect(o.get('count')).toBe(5); - expect(o.op('count')).toBe(undefined); + expect(o.get("cool")).toBe(undefined); + expect(o.op("cool")).toBe(undefined); + expect(o.get("count")).toBe(5); + expect(o.op("count")).toBe(undefined); }); - it('can revert a specific field in unsaved ops', () => { + it("can revert a specific field in unsaved ops", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'canrevertspecific', - count: 5 + className: "Item", + objectId: "canrevertspecific", + count: 5, }); o.set({ cool: true }); - o.increment('count'); - expect(o.get('cool')).toBe(true); - expect(o.get('count')).toBe(6); - o.revert('cool'); - expect(o.get('cool')).toBe(undefined); - expect(o.op('cool')).toBe(undefined); - expect(o.get('count')).toBe(6); - expect(o.op('count')).not.toBe(undefined); + o.increment("count"); + expect(o.get("cool")).toBe(true); + expect(o.get("count")).toBe(6); + o.revert("cool"); + expect(o.get("cool")).toBe(undefined); + expect(o.op("cool")).toBe(undefined); + expect(o.get("count")).toBe(6); + expect(o.op("count")).not.toBe(undefined); }); - it('can revert multiple fields in unsaved ops', () => { + it("can revert multiple fields in unsaved ops", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'canrevertmultiple', + className: "Item", + objectId: "canrevertmultiple", count: 5, age: 18, - gender: 'female' - }); - o.set({ cool: true, gender: 'male' }); - o.increment('count'); - o.increment('age'); - expect(o.get('cool')).toBe(true); - expect(o.get('count')).toBe(6); - expect(o.get('age')).toBe(19); - expect(o.get('gender')).toBe('male'); - o.revert('age', 'count', 'gender'); - expect(o.get('cool')).toBe(true); - expect(o.op('cool')).not.toBe(undefined); - expect(o.get('count')).toBe(5); - expect(o.op('count')).toBe(undefined); - expect(o.get('age')).toBe(18); - expect(o.op('age')).toBe(undefined); - expect(o.get('gender')).toBe('female'); - expect(o.op('gender')).toBe(undefined); - }); - - it('throws if an array is provided', () => { + gender: "female", + }); + o.set({ cool: true, gender: "male" }); + o.increment("count"); + o.increment("age"); + expect(o.get("cool")).toBe(true); + expect(o.get("count")).toBe(6); + expect(o.get("age")).toBe(19); + expect(o.get("gender")).toBe("male"); + o.revert("age", "count", "gender"); + expect(o.get("cool")).toBe(true); + expect(o.op("cool")).not.toBe(undefined); + expect(o.get("count")).toBe(5); + expect(o.op("count")).toBe(undefined); + expect(o.get("age")).toBe(18); + expect(o.op("age")).toBe(undefined); + expect(o.get("gender")).toBe("female"); + expect(o.op("gender")).toBe(undefined); + }); + + it("throws if an array is provided", () => { const o = ParseObject.fromJSON({ - className: 'Item', - objectId: 'throwforarray', + className: "Item", + objectId: "throwforarray", count: 5, age: 18, - gender: 'female' + gender: "female", }); - o.set({ cool: true, gender: 'male' }); + 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 () => { + 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']); - await parent.fetchWithInclude([['child']]); + const parent = new ParseObject("Person"); + 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'] } + parent, + true, + { useMasterKey: true, sessionToken: "123", include: ["child"] }, ]); expect(objectController.fetch.mock.calls[1]).toEqual([ - parent, true, { include: ['child'] } + parent, + true, + { include: ["child"] }, ]); expect(objectController.fetch.mock.calls[2]).toEqual([ - parent, true, { include: ['child'] } + parent, + true, + { include: ["child"] }, ]); spy.mockRestore(); }); - it('fetchAll with empty values', async () => { + 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'); + jest.spyOn(controller, "ajax"); const results = await ParseObject.fetchAll([]); expect(results).toEqual([]); expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it('fetchAll with null', async () => { + it("fetchAll with null", async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, 'ajax'); + jest.spyOn(controller, "ajax"); const results = await ParseObject.fetchAll(null); expect(results).toEqual(undefined); expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it('fetchAll unique instance', async () => { + it("fetchAll unique instance", async () => { ParseObject.disableSingleInstance(); - const obj = new ParseObject('Item'); - obj.id = 'fetch0'; + const obj = new ParseObject("Item"); + obj.id = "fetch0"; const results = await ParseObject.fetchAll([obj]); expect(results[0].id).toEqual(obj.id); }); - it('fetchAll objects does not exist on server', async () => { - jest.spyOn(mockQuery.prototype, 'find').mockImplementationOnce(() => { + it("fetchAll objects does not exist on server", async () => { + jest.spyOn(mockQuery.prototype, "find").mockImplementationOnce(() => { return Promise.resolve([]); }); - const obj = new ParseObject('Item'); - obj.id = 'fetch-1'; + const obj = new ParseObject("Item"); + obj.id = "fetch-1"; try { await ParseObject.fetchAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('All objects must exist on the server.'); + expect(e.message).toBe("All objects must exist on the server."); } }); - it('fetchAll unsaved objects', async () => { - const obj = new ParseObject('Item'); + it("fetchAll unsaved objects", async () => { + const obj = new ParseObject("Item"); try { await ParseObject.fetchAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('All objects must have an ID'); + expect(e.message).toBe("All objects must have an ID"); } }); - it('fetchAll objects with different classes', async () => { - const obj = new ParseObject('Item'); - const obj2 = new ParseObject('TestObject'); + it("fetchAll objects with different classes", async () => { + const obj = new ParseObject("Item"); + const obj2 = new ParseObject("TestObject"); try { await ParseObject.fetchAll([obj, obj2]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('All objects must have an ID'); + expect(e.message).toBe("All objects must have an ID"); } }); - it('fetchAll saved objects with different classes', async () => { - const obj1 = new ParseObject('Item'); - const obj2 = new ParseObject('TestObject'); - obj1.id = 'fetch1'; - obj2.id = 'fetch2'; + it("fetchAll saved objects with different classes", async () => { + const obj1 = new ParseObject("Item"); + const obj2 = new ParseObject("TestObject"); + obj1.id = "fetch1"; + obj2.id = "fetch2"; try { await ParseObject.fetchAll([obj1, obj2]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('All objects should be of the same class'); + expect(e.message).toBe("All objects should be of the same class"); } }); - it('can fetchAllWithInclude', async () => { + 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']); - await ParseObject.fetchAllWithInclude([parent], [['child']]); + const parent = new ParseObject("Person"); + 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'] } + [parent], + true, + { useMasterKey: true, sessionToken: "123", include: ["child"] }, ]); expect(objectController.fetch.mock.calls[1]).toEqual([ - [parent], true, { include: ['child'] } + [parent], + true, + { include: ["child"] }, ]); expect(objectController.fetch.mock.calls[2]).toEqual([ - [parent], true, { include: ['child'] } + [parent], + true, + { include: ["child"] }, ]); spy.mockRestore(); }); - it('can fetchAllIfNeededWithInclude', async () => { + 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']); - await ParseObject.fetchAllIfNeededWithInclude([parent], [['child']]); + const parent = new ParseObject("Person"); + 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'] } + [parent], + false, + { useMasterKey: true, sessionToken: "123", include: ["child"] }, ]); expect(objectController.fetch.mock.calls[1]).toEqual([ - [parent], false, { include: ['child'] } + [parent], + false, + { include: ["child"] }, ]); expect(objectController.fetch.mock.calls[2]).toEqual([ - [parent], false, { include: ['child'] } + [parent], + false, + { include: ["child"] }, ]); spy.mockRestore(); }); - it('can check if object exists', async () => { - const parent = new ParseObject('Person'); + 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(() => { + jest.spyOn(mockQuery.prototype, "get").mockImplementationOnce(() => { return Promise.reject({ code: 101, }); }); expect(await parent.exists()).toBe(false); - jest.spyOn(mockQuery.prototype, 'get').mockImplementationOnce(() => { + jest.spyOn(mockQuery.prototype, "get").mockImplementationOnce(() => { return Promise.reject({ code: 1, - message: 'Internal Server Error', + message: "Internal Server Error", }); }); try { @@ -1488,148 +1555,165 @@ 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'); + const p = new ParseObject("Person"); + p.set("age", 38); + p.increment("count"); p.save().then((obj) => { expect(obj).toBe(p); - expect(obj.get('age')).toBe(38); - expect(obj.get('count')).toBe(1); - expect(obj.op('age')).toBe(undefined); + expect(obj.get("age")).toBe(38); + expect(obj.get("count")).toBe(1); + expect(obj.op("age")).toBe(undefined); expect(obj.dirty()).toBe(false); done(); }); }); - 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) => { + const p = new ParseObject("Person"); + p.save("foo", "bar").then((obj) => { expect(obj).toBe(p); - expect(obj.get('foo')).toBe('bar'); + 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 = new ParseObject('Item'); - return o.save({ ACL: 'not an acl' }); - }).then(null, (error) => { - expect(error.code).toBe(-1); - done(); - }); + let o = new ParseObject("Item"); + 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(); + }); }); - it('accepts context on save', async () => { + 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'); + jest.spyOn(controller, "ajax"); // Save object - const context = {a: "a"}; - const obj = new ParseObject('Item'); - await obj.save(null, {context}); + const context = { a: "a" }; + const obj = new ParseObject("Item"); + 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(() => { - expect(o.get('key')).toBe('value'); - expect(o.get('deletedKey')).toBeUndefined(); + const o = new ParseObject("Item"); + o.save({ key: "value", deletedKey: "keyToDelete" }).then(() => { + expect(o.get("key")).toBe("value"); + expect(o.get("deletedKey")).toBeUndefined(); done(); }); }); - it('can make changes while in the process of a save', async () => { + it("can make changes while in the process of a save", async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - const p = new ParseObject('Person'); - p.set('age', 38); + RESTController._setXHR(function () { + return xhr; + }); + const p = new ParseObject("Person"); + p.set("age", 38); const result = p.save().then(() => { expect(p._getServerData()).toEqual({ age: 38 }); expect(p._getPendingOps().length).toBe(1); - expect(p.get('age')).toBe(39); + expect(p.get("age")).toBe(39); }); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); - p.increment('age'); - expect(p.get('age')).toBe(39); + p.increment("age"); + expect(p.get("age")).toBe(39); xhr.status = 200; - xhr.responseText = JSON.stringify({ objectId: 'P12' }); + xhr.responseText = JSON.stringify({ objectId: "P12" }); xhr.readyState = 4; xhr.onreadystatechange(); await result; }); - it('will queue save operations', async () => { + 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; }); - const p = new ParseObject('Person'); + const p = new ParseObject("Person"); expect(p._getPendingOps().length).toBe(1); expect(xhrs.length).toBe(0); - p.increment('updates'); + p.increment("updates"); p.save(); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); expect(xhrs.length).toBe(1); - p.increment('updates'); + p.increment("updates"); p.save(); jest.runAllTicks(); await flushPromises(); @@ -1637,64 +1721,69 @@ describe('ParseObject', () => { expect(xhrs.length).toBe(1); xhrs[0].status = 200; - xhrs[0].responseText = JSON.stringify({ objectId: 'P15', updates: 1 }); + xhrs[0].responseText = JSON.stringify({ objectId: "P15", updates: 1 }); xhrs[0].readyState = 4; xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); expect(p._getServerData()).toEqual({ updates: 1 }); - expect(p.get('updates')).toBe(2); + expect(p.get("updates")).toBe(2); expect(p._getPendingOps().length).toBe(2); expect(xhrs.length).toBe(2); }); - it('will leave the pending ops queue untouched when a lone save fails', async () => { + it("will leave the pending ops queue untouched when a lone save fails", async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - const p = new ParseObject('Per$on'); + RESTController._setXHR(function () { + return xhr; + }); + const p = new ParseObject("Per$on"); expect(p._getPendingOps().length).toBe(1); - p.increment('updates'); + p.increment("updates"); const result = p.save().then(null, (err) => { expect(err.code).toBe(103); - expect(err.message).toBe('Invalid class name'); + expect(err.message).toBe("Invalid class name"); expect(p._getPendingOps().length).toBe(1); - expect(p.dirtyKeys()).toEqual(['updates']); - expect(p.get('updates')).toBe(1); + expect(p.dirtyKeys()).toEqual(["updates"]); + expect(p.get("updates")).toBe(1); }); jest.runAllTicks(); 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; }); - it('will merge pending Ops when a save fails and others are pending', async () => { + 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; }); - const p = new ParseObject('Per$on'); + const p = new ParseObject("Per$on"); expect(p._getPendingOps().length).toBe(1); - p.increment('updates'); + p.increment("updates"); p.save().catch(() => {}); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); - p.set('updates', 12); + p.set("updates", 12); p.save().catch(() => {}); jest.runAllTicks(); await flushPromises(); @@ -1702,285 +1791,305 @@ 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 () => { + 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; }); - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - child.set('value', 5); - parent.set('child', child); + const parent = new ParseObject("Item"); + const child = new ParseObject("Item"); + child.set("value", 5); + parent.set("child", child); const result = parent.save().then(() => { - expect(child.id).toBe('child'); + expect(child.id).toBe("child"); expect(child.dirty()).toBe(false); - expect(parent.id).toBe('parent'); + expect(parent.id).toBe("parent"); }); jest.runAllTicks(); 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(); expect(xhrs.length).toBe(2); - xhrs[1].responseText = JSON.stringify({ objectId: 'parent' }); + xhrs[1].responseText = JSON.stringify({ objectId: "parent" }); xhrs[1].onreadystatechange(); jest.runAllTicks(); await result; }); - it('will fail for a circular dependency of non-existing objects', () => { - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - parent.set('child', child); - child.set('parent', parent); + it("will fail for a circular dependency of non-existing objects", () => { + const parent = new ParseObject("Item"); + 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.' + "Cannot create a pointer to an unsaved Object." ); }); - it('will fail for deeper unsaved objects', () => { - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - const grandchild = new ParseObject('Item'); - parent.set('child', child); - child.set('child', grandchild); + it("will fail for deeper unsaved objects", () => { + const parent = new ParseObject("Item"); + const child = new ParseObject("Item"); + const grandchild = new ParseObject("Item"); + parent.set("child", child); + child.set("child", grandchild); expect(parent.save.bind(parent)).toThrow( - 'Cannot create a pointer to an unsaved Object.' + "Cannot create a pointer to an unsaved Object." ); }); - it('does not mark shallow objects as dirty', () => { - const post = new ParseObject('Post'); - post.id = '141414'; + it("does not mark shallow objects as dirty", () => { + const post = new ParseObject("Post"); + post.id = "141414"; expect(post.dirty()).toBe(false); - const comment = new ParseObject('Comment'); - comment.set('parent', post); + const comment = new ParseObject("Comment"); + comment.set("parent", post); expect(unsavedChildren(comment)).toEqual([]); }); - it('can fetch an object given an id', async () => { + 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'; + const p = new ParseObject("Person"); + p.id = "P55"; await p.fetch().then((res) => { expect(p).toBe(res); expect(p.attributes).toEqual({ count: 10 }); }); }); - it('throw for fetch with empty string as ID', async () => { + 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") ); - 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' - )); - }); - - it('should fail saveAll batch cycle', async () => { - const obj = new ParseObject('Item'); - obj.set('child', obj); + }); + + it("should fail saveAll batch cycle", async () => { + const obj = new ParseObject("Item"); + obj.set("child", obj); try { await ParseObject.saveAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('Tried to save a batch with a cycle.'); + expect(e.message).toBe("Tried to save a batch with a cycle."); } }); - 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(); - }); + 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(); + }); jest.runAllTicks(); }); - it('can save a ring of objects, given one exists', async () => { + 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; }); - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - child.id = 'child'; - parent.set('child', child); - child.set('parent', parent); + const parent = new ParseObject("Item"); + const child = new ParseObject("Item"); + child.id = "child"; + parent.set("child", child); + child.set("parent", parent); const result = ParseObject.saveAll([parent, child]).then(() => { expect(child.dirty()).toBe(false); - expect(parent.id).toBe('parent'); + expect(parent.id).toBe("parent"); }); jest.runAllTicks(); 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( - [{ - method: 'POST', - path: '/1/classes/Item', + 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' } } ]); + __type: "Pointer", + className: "Item", + objectId: "child", + }, + }, + }, + ]); + xhrs[0].responseText = JSON.stringify([ + { success: { objectId: "parent" } }, + ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); - expect(parent.id).toBe('parent'); + 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(); await result; }); - it('accepts context on saveAll', async () => { + 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'); + jest.spyOn(controller, "ajax"); // Save object - const context = {a: "saveAll"}; - const obj = new ParseObject('Item'); - obj.id = 'pid'; - obj.set('test', 'value'); - await ParseObject.saveAll([obj], { context, useMasterKey: true }) + const context = { a: "saveAll" }; + const obj = new ParseObject("Item"); + obj.id = "pid"; + obj.set("test", "value"); + await ParseObject.saveAll([obj], { context, useMasterKey: true }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it('accepts context on destroyAll', async () => { + 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'); + jest.spyOn(controller, "ajax"); // Save object - const context = {a: "b"}; - const obj = new ParseObject('Item'); - obj.id = 'pid'; - await ParseObject.destroyAll([obj], { context: context }) + const context = { a: "b" }; + const obj = new ParseObject("Item"); + obj.id = "pid"; + await ParseObject.destroyAll([obj], { context: context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it('destroyAll with options', async () => { + 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'); + jest.spyOn(controller, "ajax"); - const obj = new ParseObject('Item'); - obj.id = 'pid'; + const obj = new ParseObject("Item"); + obj.id = "pid"; await ParseObject.destroyAll([obj], { useMasterKey: true, - sessionToken: 'r:1234', + sessionToken: "r:1234", batchSize: 25, }); const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); - expect(jsonBody._MasterKey).toBe('C') - expect(jsonBody._SessionToken).toBe('r:1234'); + expect(jsonBody._MasterKey).toBe("C"); + expect(jsonBody._SessionToken).toBe("r:1234"); }); - it('destroyAll with empty values', async () => { + 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'); + jest.spyOn(controller, "ajax"); let results = await ParseObject.destroyAll([]); expect(results).toEqual([]); @@ -1990,37 +2099,43 @@ describe('ParseObject', () => { expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it('destroyAll unsaved objects', async () => { + it("destroyAll unsaved objects", async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, 'ajax'); + 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); }); - it('destroyAll handle error response', async () => { + 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') - obj.id = 'toDelete1'; + const obj = new ParseObject("Item"); + obj.id = "toDelete1"; try { await ParseObject.destroyAll([obj]); expect(true).toBe(false); @@ -2029,163 +2144,184 @@ describe('ParseObject', () => { } }); - it('can save a chain of unsaved objects', async () => { + 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; }); - const parent = new ParseObject('Item'); - const child = new ParseObject('Item'); - const grandchild = new ParseObject('Item'); - parent.set('child', child); - child.set('child', grandchild); + const parent = new ParseObject("Item"); + const child = new ParseObject("Item"); + const grandchild = new ParseObject("Item"); + parent.set("child", child); + child.set("child", grandchild); const result = ParseObject.saveAll([parent]).then(() => { expect(child.dirty()).toBe(false); expect(grandchild.dirty()).toBe(false); - expect(parent.id).toBe('parent'); - expect(child.id).toBe('child'); - expect(grandchild.id).toBe('grandchild'); + expect(parent.id).toBe("parent"); + expect(child.id).toBe("child"); + expect(grandchild.id).toBe("grandchild"); }); jest.runAllTicks(); 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( - [{ - method: 'POST', - path: '/1/classes/Item', - body: {} - }] - ); - xhrs[0].responseText = JSON.stringify([ { success: { objectId: 'grandchild' } } ]); + 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" } }, + ]); 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( - [{ - method: 'POST', - path: '/1/classes/Item', + 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' } } ]); + __type: "Pointer", + className: "Item", + 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( - [{ - method: 'POST', - path: '/1/classes/Item', + 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' } } ]); + __type: "Pointer", + className: "Item", + 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(); - }); + 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(); + }); }); - 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 + className: "Person", + objectId: "P200", + name: "Fred", + count: 0, }); - expect(p.get('name')).toBe('Fred'); - expect(p.get('count')).toBe(0); + expect(p.get("name")).toBe("Fred"); + expect(p.get("count")).toBe(0); p.fetch().then(() => { - expect(p.get('count')).toBe(10); - expect(p.get('name')).toBe(undefined); - expect(p.has('name')).toBe(false); + expect(p.get("count")).toBe(10); + expect(p.get("name")).toBe(undefined); + expect(p.has("name")).toBe(false); done(); }); }); - it('can destroy an object', async () => { + it("can destroy an object", async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - const p = new ParseObject('Person'); - p.id = 'pid'; + 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(JSON.parse(xhr.send.mock.calls[0])._method).toBe('DELETE'); + 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(); await flushPromises(); @@ -2197,57 +2333,63 @@ describe('ParseObject', () => { await result; }); - it('accepts context on destroy', async () => { + 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'); + jest.spyOn(controller, "ajax"); // Save object - const context = {a: "a"}; - const obj = new ParseObject('Item'); - obj.id = 'pid'; - await obj.destroy({context}); + const context = { a: "a" }; + const obj = new ParseObject("Item"); + obj.id = "pid"; + await obj.destroy({ context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it('handle destroy on new object', async () => { + it("handle destroy on new object", async () => { const controller = CoreManager.getRESTController(); - jest.spyOn(controller, 'ajax'); + jest.spyOn(controller, "ajax"); - const obj = new ParseObject('Item'); + const obj = new ParseObject("Item"); await obj.destroy({ useMasterKey: true }); 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'); + 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: {} + method: "POST", + path: "/1/classes/Person", + body: {}, }); done(); }); @@ -2255,18 +2397,18 @@ describe('ParseObject', () => { await flushPromises(); xhr.status = 200; xhr.responseText = JSON.stringify([ - { success: { objectId: 'pid0' } }, - { success: { objectId: 'pid1' } }, - { success: { objectId: 'pid2' } }, - { success: { objectId: 'pid3' } }, - { success: { objectId: 'pid4' } }, + { success: { objectId: "pid0" } }, + { success: { objectId: "pid1" } }, + { success: { objectId: "pid2" } }, + { success: { objectId: "pid3" } }, + { success: { objectId: "pid4" } }, ]); xhr.readyState = 4; xhr.onreadystatechange(); 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,62 +2416,68 @@ 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'); + 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(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: 'pid0' } }, - { success: { objectId: 'pid1' } }, - { success: { objectId: 'pid2' } }, - { success: { objectId: 'pid3' } }, - { success: { objectId: 'pid4' } }, - { success: { objectId: 'pid5' } }, - { success: { objectId: 'pid6' } }, - { success: { objectId: 'pid7' } }, - { success: { objectId: 'pid8' } }, - { success: { objectId: 'pid9' } }, - { success: { objectId: 'pid10' } }, - { success: { objectId: 'pid11' } }, - { success: { objectId: 'pid12' } }, - { success: { objectId: 'pid13' } }, - { success: { objectId: 'pid14' } }, - { success: { objectId: 'pid15' } }, - { success: { objectId: 'pid16' } }, - { success: { objectId: 'pid17' } }, - { success: { objectId: 'pid18' } }, - { success: { objectId: 'pid19' } }, + { success: { objectId: "pid0" } }, + { success: { objectId: "pid1" } }, + { success: { objectId: "pid2" } }, + { success: { objectId: "pid3" } }, + { success: { objectId: "pid4" } }, + { success: { objectId: "pid5" } }, + { success: { objectId: "pid6" } }, + { success: { objectId: "pid7" } }, + { success: { objectId: "pid8" } }, + { success: { objectId: "pid9" } }, + { success: { objectId: "pid10" } }, + { success: { objectId: "pid11" } }, + { success: { objectId: "pid12" } }, + { success: { objectId: "pid13" } }, + { success: { objectId: "pid14" } }, + { success: { objectId: "pid15" } }, + { success: { objectId: "pid16" } }, + { success: { objectId: "pid17" } }, + { success: { objectId: "pid18" } }, + { success: { objectId: "pid19" } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); xhrs[1].responseText = JSON.stringify([ - { success: { objectId: 'pid20' } }, - { success: { objectId: 'pid21' } }, + { success: { objectId: "pid20" } }, + { success: { objectId: "pid21" } }, ]); xhrs[1].onreadystatechange(); 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,62 +2485,68 @@ 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'); + 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(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: 'pid0' } }, - { success: { objectId: 'pid1' } }, - { success: { objectId: 'pid2' } }, - { success: { objectId: 'pid3' } }, - { success: { objectId: 'pid4' } }, - { success: { objectId: 'pid5' } }, - { success: { objectId: 'pid6' } }, - { success: { objectId: 'pid7' } }, - { success: { objectId: 'pid8' } }, - { success: { objectId: 'pid9' } }, - { success: { objectId: 'pid10' } }, - { success: { objectId: 'pid11' } }, - { success: { objectId: 'pid12' } }, - { success: { objectId: 'pid13' } }, - { success: { objectId: 'pid14' } }, - { success: { objectId: 'pid15' } }, - { success: { objectId: 'pid16' } }, - { success: { objectId: 'pid17' } }, - { success: { objectId: 'pid18' } }, - { success: { objectId: 'pid19' } }, + { success: { objectId: "pid0" } }, + { success: { objectId: "pid1" } }, + { success: { objectId: "pid2" } }, + { success: { objectId: "pid3" } }, + { success: { objectId: "pid4" } }, + { success: { objectId: "pid5" } }, + { success: { objectId: "pid6" } }, + { success: { objectId: "pid7" } }, + { success: { objectId: "pid8" } }, + { success: { objectId: "pid9" } }, + { success: { objectId: "pid10" } }, + { success: { objectId: "pid11" } }, + { success: { objectId: "pid12" } }, + { success: { objectId: "pid13" } }, + { success: { objectId: "pid14" } }, + { success: { objectId: "pid15" } }, + { success: { objectId: "pid16" } }, + { success: { objectId: "pid17" } }, + { success: { objectId: "pid18" } }, + { success: { objectId: "pid19" } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); xhrs[1].responseText = JSON.stringify([ - { success: { objectId: 'pid20' } }, - { success: { objectId: 'pid21' } }, + { success: { objectId: "pid20" } }, + { success: { objectId: "pid21" } }, ]); xhrs[1].onreadystatechange(); 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,14 +2554,16 @@ 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'); + objects[i] = new ParseObject("Person"); } ParseObject.saveAll(objects).then(null, (error) => { // The second batch never ran @@ -2415,59 +2571,63 @@ describe('ParseObject', () => { expect(objects[19].dirty()).toBe(false); expect(objects[20].dirty()).toBe(true); - expect(error.message).toBe('first error'); + expect(error.message).toBe("first error"); done(); }); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: 'pid0' } }, - { success: { objectId: 'pid1' } }, - { success: { objectId: 'pid2' } }, - { success: { objectId: 'pid3' } }, - { success: { objectId: 'pid4' } }, - { success: { objectId: 'pid5' } }, - { error: { code: -1, error: 'first error' } }, - { success: { objectId: 'pid7' } }, - { success: { objectId: 'pid8' } }, - { success: { objectId: 'pid9' } }, - { success: { objectId: 'pid10' } }, - { success: { objectId: 'pid11' } }, - { success: { objectId: 'pid12' } }, - { success: { objectId: 'pid13' } }, - { success: { objectId: 'pid14' } }, - { error: { code: -1, error: 'second error' } }, - { success: { objectId: 'pid16' } }, - { success: { objectId: 'pid17' } }, - { success: { objectId: 'pid18' } }, - { success: { objectId: 'pid19' } }, + { success: { objectId: "pid0" } }, + { success: { objectId: "pid1" } }, + { success: { objectId: "pid2" } }, + { success: { objectId: "pid3" } }, + { success: { objectId: "pid4" } }, + { success: { objectId: "pid5" } }, + { error: { code: -1, error: "first error" } }, + { success: { objectId: "pid7" } }, + { success: { objectId: "pid8" } }, + { success: { objectId: "pid9" } }, + { success: { objectId: "pid10" } }, + { success: { objectId: "pid11" } }, + { success: { objectId: "pid12" } }, + { success: { objectId: "pid13" } }, + { success: { objectId: "pid14" } }, + { error: { code: -1, error: "second error" } }, + { success: { objectId: "pid16" } }, + { success: { objectId: "pid17" } }, + { success: { objectId: "pid18" } }, + { success: { objectId: "pid19" } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); }); }); -describe('ObjectController', () => { +describe("ObjectController", () => { beforeEach(() => { 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; }); - const o = new ParseObject('Person'); - o.id = 'pid'; + 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'); + expect(body._method).toBe("GET"); done(); }); await flushPromises(); @@ -2479,59 +2639,65 @@ describe('ObjectController', () => { jest.runAllTicks(); }); - it('accepts context on fetch', async () => { + 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(); - jest.spyOn(controller, 'ajax'); + jest.spyOn(controller, "ajax"); // Save object - const context = { a: 'fetch' }; - const obj = new ParseObject('Item'); - obj.id = 'pid'; + const context = { a: "fetch" }; + const obj = new ParseObject("Item"); + obj.id = "pid"; await obj.fetch({ context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); 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; + objects[i] = new ParseObject("Person"); + objects[i].id = "pid" + i; } objectController.fetch(objects).then((results) => { expect(results.length).toBe(5); expect(results[0] instanceof ParseObject).toBe(true); - expect(results[0].id).toBe('pid0'); - expect(results[0].className).toBe('Person'); + expect(results[0].id).toBe("pid0"); + expect(results[0].className).toBe("Person"); done(); }); }); - 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; }); - 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] - ); + 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, + ]); const body = JSON.parse(xhr.send.mock.calls[0]); - expect(body._method).toBe('GET'); + expect(body._method).toBe("GET"); done(); }); await flushPromises(); @@ -2543,53 +2709,64 @@ describe('ObjectController', () => { jest.runAllTicks(); }); - it('can fetch an array of objects with include', async () => { + it("can fetch an array of objects with include", async () => { const objectController = CoreManager.getObjectController(); const objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject('Person'); - objects[i].id = 'pid' + i; + 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'); - expect(results[0].className).toBe('Person'); + expect(results[0].id).toBe("pid0"); + expect(results[0].className).toBe("Person"); }); - it('can destroy an object', async () => { + it("can destroy an object", async () => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - 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 - }); - 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'); + 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, + }); + 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; @@ -2600,73 +2777,84 @@ describe('ObjectController', () => { await result; }); - it('can destroy an array of objects with batchSize', async () => { + it("can destroy an array of objects with batchSize", async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { 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; + 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(); @@ -2675,73 +2863,84 @@ describe('ObjectController', () => { await result; }); - it('can destroy an array of objects', async () => { + it("can destroy an array of objects", async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { 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; + 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(); @@ -2750,23 +2949,27 @@ describe('ObjectController', () => { await result; }); - it('can save an object', async () => { + it("can save an object", async () => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - const p = new ParseObject('Person'); - p.id = 'pid'; - p.set('key', 'value'); + 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'); + expect(body.key).toBe("value"); }); jest.runAllTicks(); await flushPromises(); @@ -2778,7 +2981,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(); @@ -2786,7 +2989,7 @@ describe('ObjectController', () => { jest.runAllTicks(); }); - it('can save an array of files', async () => { + it("can save an array of files", async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 4; i++) { @@ -2795,34 +2998,30 @@ 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("parse.txt", { base64: "ParseA==" }), + new ParseFile("parse2.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(); - const names = ['parse.txt', 'parse2.txt', 'parse3.txt']; + const names = ["parse.txt", "parse2.txt", "parse3.txt"]; for (let i = 0; i < 3; i++) { xhrs[i].responseText = JSON.stringify({ - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/' + names[i] + name: "parse.txt", + url: "http://files.parsetfss.com/a/" + names[i], }); await flushPromises(); xhrs[i].onreadystatechange(); @@ -2831,7 +3030,7 @@ describe('ObjectController', () => { await result; }); - it('can save an array of objects', async () => { + it("can save an array of objects", async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { @@ -2840,76 +3039,84 @@ 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'); + 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([ - { success: { objectId: 'pid0', index: 0 } }, - { success: { objectId: 'pid1', index: 1 } }, - { success: { objectId: 'pid2', index: 2 } }, - { success: { objectId: 'pid3', index: 3 } }, - { success: { objectId: 'pid4', index: 4 } }, + { success: { objectId: "pid0", index: 0 } }, + { success: { objectId: "pid1", index: 1 } }, + { success: { objectId: "pid2", index: 2 } }, + { success: { objectId: "pid3", index: 3 } }, + { success: { objectId: "pid4", index: 4 } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await result; }); - it('does not fail when checking if arrays of pointers are dirty', async () => { + it("does not fail when checking if arrays of pointers are dirty", async () => { const xhrs = []; for (let i = 0; i < 2; i++) { xhrs[i] = { @@ -2917,193 +3124,203 @@ describe('ObjectController', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); - xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'i333' } }]); + 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' }] + className: "Brand", + objectId: "b123", + 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(); + const items = brand.get("items"); + items.push(new ParseObject("Item")); + brand.set("items", items); + expect(function () { + brand.save(); + }).not.toThrow(); jest.runAllTicks(); await flushPromises(); xhrs[0].onreadystatechange(); }); - it('can create a new instance of an object', () => { + it("can create a new instance of an object", () => { const o = ParseObject.fromJSON({ - className: 'Clone', - objectId: 'C12', + className: "Clone", + objectId: "C12", }); const o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); o.set({ valid: true }); - expect(o2.get('valid')).toBe(true); + expect(o2.get("valid")).toBe(true); expect(o).not.toBe(o2); }); - it('cannot create a new instance of an object without className', () => { + it("cannot create a new instance of an object without className", () => { expect(() => { ParseObject.fromJSON({}); - }).toThrow('Cannot create an object without a className'); + }).toThrow("Cannot create an object without a className"); }); }); -describe('ParseObject (unique instance mode)', () => { +describe("ParseObject (unique instance mode)", () => { beforeEach(() => { ParseObject.disableSingleInstance(); }); - it('can be created with initial attributes', () => { + it("can be created with initial attributes", () => { const o = new ParseObject({ - className: 'Item', - value: 12 + className: "Item", + value: 12, }); - expect(o.className).toBe('Item'); + expect(o.className).toBe("Item"); expect(o.attributes).toEqual({ value: 12 }); }); - it('can be inflated from server JSON', () => { + it("can be inflated from server JSON", () => { const json = { - className: 'Item', - createdAt: '2013-12-14T04:51:19Z', - objectId: 'I1', - size: 'medium' + className: "Item", + createdAt: "2013-12-14T04:51:19Z", + objectId: "I1", + size: "medium", }; const o = ParseObject.fromJSON(json); - expect(o.className).toBe('Item'); - expect(o.id).toBe('I1'); + expect(o.className).toBe("Item"); + expect(o.id).toBe("I1"); expect(o.attributes).toEqual({ - size: 'medium', + 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); }); - it('can be rendered to JSON', () => { - let o = new ParseObject('Item'); + it("can be rendered to JSON", () => { + let o = new ParseObject("Item"); o.set({ - size: 'large', - inStock: 18 + size: "large", + inStock: 18, }); expect(o.toJSON()).toEqual({ - size: 'large', - inStock: 18 + size: "large", + inStock: 18, }); - o = new ParseObject('Item'); + o = new ParseObject("Item"); o._finishFetch({ - objectId: 'O2', - size: 'medium', - inStock: 12 + objectId: "O2", + size: "medium", + inStock: 12, }); - expect(o.id).toBe('O2'); + expect(o.id).toBe("O2"); expect(o.toJSON()).toEqual({ - objectId: 'O2', - size: 'medium', - inStock: 12 + objectId: "O2", + size: "medium", + inStock: 12, }); }); - it('can add, update, and remove attributes', () => { + it("can add, update, and remove attributes", () => { const o = new ParseObject({ - className: 'Item', - objectId: 'anObjectId', + className: "Item", + objectId: "anObjectId", value: 12, - valid: true + valid: true, }); o.set({ value: 14 }); - expect(o.get('value')).toBe(14); - o.unset('valid'); - expect(o.get('valid')).toBe(undefined); - expect(o.dirtyKeys()).toEqual(['value', 'valid']); - o.increment('value'); - expect(o.get('value')).toEqual(15); + expect(o.get("value")).toBe(14); + o.unset("valid"); + expect(o.get("valid")).toBe(undefined); + expect(o.dirtyKeys()).toEqual(["value", "valid"]); + o.increment("value"); + expect(o.get("value")).toEqual(15); o.clear(); - expect(o.get('value')).toBe(undefined); + expect(o.get("value")).toBe(undefined); const o2 = ParseObject.fromJSON({ - className: 'Item', - tags: ['#tbt'] + className: "Item", + tags: ["#tbt"], }); - o2.add('tags', '#nofilter'); - expect(o2.get('tags')).toEqual(['#tbt', '#nofilter']); + o2.add("tags", "#nofilter"); + expect(o2.get("tags")).toEqual(["#tbt", "#nofilter"]); o2.revert(); - o2.addUnique('tags', '#tbt'); - expect(o2.get('tags')).toEqual(['#tbt']); + o2.addUnique("tags", "#tbt"); + expect(o2.get("tags")).toEqual(["#tbt"]); o2.revert(); - o2.remove('tags', '#tbt'); - expect(o2.get('tags')).toEqual([]); + o2.remove("tags", "#tbt"); + 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'); + const p = new ParseObject("Person"); + p.set("age", 38); + p.increment("count"); p.save().then((obj) => { expect(obj).toBe(p); - expect(obj.get('age')).toBe(38); - expect(obj.get('count')).toBe(1); - expect(obj.op('age')).toBe(undefined); + expect(obj.get("age")).toBe(38); + expect(obj.get("count")).toBe(1); + expect(obj.op("age")).toBe(undefined); expect(obj.dirty()).toBe(false); done(); }); }); - it('can save an array of objects', async () => { + it("can save an array of objects", async () => { 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'); + 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: {} + method: "POST", + path: "/1/classes/Person", + body: {}, }); }); jest.runAllTicks(); xhr.status = 200; xhr.responseText = JSON.stringify([ - { success: { objectId: 'pid0' } }, - { success: { objectId: 'pid1' } }, - { success: { objectId: 'pid2' } }, - { success: { objectId: 'pid3' } }, - { success: { objectId: 'pid4' } }, + { success: { objectId: "pid0" } }, + { success: { objectId: "pid1" } }, + { success: { objectId: "pid2" } }, + { success: { objectId: "pid3" } }, + { success: { objectId: "pid4" } }, ]); await flushPromises(); xhr.readyState = 4; @@ -3112,55 +3329,55 @@ describe('ParseObject (unique instance mode)', () => { await result; }); - it('preserves changes when changing the id', () => { + it("preserves changes when changing the id", () => { const o = new ParseObject({ - className: 'Item', - objectId: 'anObjectId', - value: 12 + className: "Item", + objectId: "anObjectId", + value: 12, }); - o.id = 'otherId'; - expect(o.get('value')).toBe(12); + o.id = "otherId"; + expect(o.get("value")).toBe(12); }); - it('can maintain differences between two instances of an object', () => { + it("can maintain differences between two instances of an object", () => { const o = new ParseObject({ - className: 'Item', - objectId: 'anObjectId', - value: 12 + className: "Item", + objectId: "anObjectId", + value: 12, }); const o2 = new ParseObject({ - className: 'Item', - objectId: 'anObjectId', - value: 12 + className: "Item", + objectId: "anObjectId", + value: 12, }); o.set({ value: 100 }); - expect(o.get('value')).toBe(100); - expect(o2.get('value')).toBe(12); + expect(o.get("value")).toBe(100); + expect(o2.get("value")).toBe(12); - o2.set({ name: 'foo' }); - expect(o.has('name')).toBe(false); - expect(o2.has('name')).toBe(true); + o2.set({ name: "foo" }); + expect(o.has("name")).toBe(false); + expect(o2.has("name")).toBe(true); }); - it('can create a new instance of an object', () => { + it("can create a new instance of an object", () => { const o = ParseObject.fromJSON({ - className: 'Clone', - objectId: 'C14', + className: "Clone", + objectId: "C14", }); let o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); expect(o).not.toBe(o2); o.set({ valid: true }); - expect(o2.get('valid')).toBe(undefined); + expect(o2.get("valid")).toBe(undefined); o2 = o.newInstance(); - expect(o2.get('valid')).toBe(true); + expect(o2.get("valid")).toBe(true); }); }); class MyObject extends ParseObject { constructor() { - super('MyObject'); + super("MyObject"); } doSomething() { @@ -3168,248 +3385,273 @@ class MyObject extends ParseObject { } static readOnlyAttributes() { - return ['readonly', 'static', 'frozen']; + return ["readonly", "static", "frozen"]; } } -ParseObject.registerSubclass('MyObject', MyObject); +ParseObject.registerSubclass("MyObject", MyObject); -describe('ParseObject Subclasses', () => { +describe("ParseObject Subclasses", () => { beforeEach(() => { ParseObject.enableSingleInstance(); }); - it('can be extended with ES6 classes', () => { + it("can be extended with ES6 classes", () => { const o = new MyObject(); - expect(o.className).toBe('MyObject'); - expect(MyObject.className).toBe('MyObject'); - o.id = 'anObjectId'; + expect(o.className).toBe("MyObject"); + expect(MyObject.className).toBe("MyObject"); + o.id = "anObjectId"; expect(o.toPointer()).toEqual({ - __type: 'Pointer', - className: 'MyObject', - objectId: 'anObjectId' + __type: "Pointer", + className: "MyObject", + objectId: "anObjectId", }); expect(o.doSomething()).toBe(5); - const o2 = MyObject.createWithoutData('otherId'); + const o2 = MyObject.createWithoutData("otherId"); expect(o2 instanceof ParseObject).toBe(true); expect(o2 instanceof MyObject).toBe(true); expect(o2.toPointer()).toEqual({ - __type: 'Pointer', - className: 'MyObject', - objectId: 'otherId' + __type: "Pointer", + className: "MyObject", + objectId: "otherId", }); expect(o2.doSomething()).toBe(5); }); - it('respects readonly attributes of 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' + 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, "static")).toThrow( + "Cannot modify readonly attribute: static" ); - expect(o.set.bind(o, 'frozen')).toThrow( - 'Cannot modify readonly attribute: frozen' + expect(o.set.bind(o, "frozen")).toThrow( + "Cannot modify readonly attribute: frozen" ); }); - it('registerSubclass errors', () => { + it("registerSubclass errors", () => { expect(() => { ParseObject.registerSubclass(1234); - }).toThrow('The first argument must be a valid class name.'); + }).toThrow("The first argument must be a valid class name."); expect(() => { - ParseObject.registerSubclass('TestObject', undefined); - }).toThrow('You must supply a subclass constructor.'); + ParseObject.registerSubclass("TestObject", undefined); + }).toThrow("You must supply a subclass constructor."); expect(() => { - ParseObject.registerSubclass('TestObject', {}); - }).toThrow('You must register the subclass constructor. Did you attempt to register an instance of the subclass?'); + ParseObject.registerSubclass("TestObject", {}); + }).toThrow( + "You must register the subclass constructor. Did you attempt to register an instance of the subclass?" + ); }); - it('can inflate subclasses from server JSON', () => { + it("can inflate subclasses from server JSON", () => { const json = { - className: 'MyObject', - objectId: 'anotherId' + className: "MyObject", + objectId: "anotherId", }; const o = ParseObject.fromJSON(json); expect(o instanceof ParseObject).toBe(true); - expect(o.className).toBe('MyObject'); - expect(o.id).toBe('anotherId'); + expect(o.className).toBe("MyObject"); + expect(o.id).toBe("anotherId"); expect(o.doSomething()).toBe(5); }); - it('can be cloned', () => { + it("can be cloned", () => { const o = new MyObject(); o.set({ - size: 'large', - count: 7 + size: "large", + count: 7, }); const o2 = o.clone(); expect(o2 instanceof MyObject).toBe(true); - expect(o2.className).toBe('MyObject'); + expect(o2.className).toBe("MyObject"); expect(o2.attributes).toEqual({ - size: 'large', - count: 7 + size: "large", + count: 7, }); expect(o2.id).toBe(undefined); expect(o.equals(o2)).toBe(false); }); - it('can be cleared', () => { + it("can be cleared", () => { const o = new MyObject(); o.set({ - size: 'large', + size: "large", count: 7, }); - jest.spyOn(o, 'set'); + 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, + } + ); }); }); -describe('ParseObject extensions', () => { +describe("ParseObject extensions", () => { beforeEach(() => { ParseObject.enableSingleInstance(); }); - it('can generate ParseObjects with a default className', () => { - const YourObject = ParseObject.extend('YourObject'); + it("can generate ParseObjects with a default className", () => { + const YourObject = ParseObject.extend("YourObject"); const yo = new YourObject(); expect(yo instanceof ParseObject).toBe(true); expect(yo instanceof YourObject).toBe(true); - expect(yo.className).toBe('YourObject'); - yo.set('greeting', 'yo'); - expect(yo.get('greeting')).toBe('yo'); + expect(yo.className).toBe("YourObject"); + yo.set("greeting", "yo"); + expect(yo.get("greeting")).toBe("yo"); expect(yo.attributes).toEqual({ - greeting: 'yo' + greeting: "yo", }); - const yo2 = YourObject.createWithoutData('otherId'); + const yo2 = YourObject.createWithoutData("otherId"); expect(yo2 instanceof ParseObject).toBe(true); expect(yo2 instanceof YourObject).toBe(true); expect(yo2.toPointer()).toEqual({ - __type: 'Pointer', - className: 'YourObject', - objectId: 'otherId' + __type: "Pointer", + className: "YourObject", + objectId: "otherId", }); }); - it('can extend the prototype and statics of ParseObject', () => { - const ExtendedObject = ParseObject.extend('ExtendedObject', { - getFoo() { return 12; } - }, { - isFoo(value) { return value === 'foo'; } - }); + it("can extend the prototype and statics of ParseObject", () => { + 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); expect(e.getFoo()).toBe(12); expect(ExtendedObject.isFoo(12)).toBe(false); - expect(ExtendedObject.isFoo('foo')).toBe(true); + expect(ExtendedObject.isFoo("foo")).toBe(true); }); - it('can extend a previous extension', () => { - let FeatureObject = ParseObject.extend('FeatureObject', { - foo() { return 'F'; } + it("can extend a previous extension", () => { + let FeatureObject = ParseObject.extend("FeatureObject", { + foo() { + return "F"; + }, }); let f = new FeatureObject(); - expect(f.foo()).toBe('F'); - FeatureObject = ParseObject.extend('FeatureObject', { - bar() { return 'B'; } + expect(f.foo()).toBe("F"); + FeatureObject = ParseObject.extend("FeatureObject", { + bar() { + return "B"; + }, }); f = new FeatureObject(); - expect(f.foo() + f.bar()).toBe('FB'); + expect(f.foo() + f.bar()).toBe("FB"); }); - it('can specify a custom initializer', () => { - const InitObject = ParseObject.extend('InitObject', { - initialize: function() { - this.set('field', 12); - } + it("can specify a custom initializer", () => { + const InitObject = ParseObject.extend("InitObject", { + initialize: function () { + this.set("field", 12); + }, }); - const i = new InitObject() - expect(i.get('field')).toBe(12); + const i = new InitObject(); + expect(i.get("field")).toBe(12); }); - it('can handle className parameters', () => { + it("can handle className parameters", () => { expect(() => { ParseObject.extend(); }).toThrow("Parse.Object.extend's first argument should be the className."); - let CustomObject = ParseObject.extend('Item'); - expect(CustomObject.className).toBe('Item'); + let CustomObject = ParseObject.extend("Item"); + expect(CustomObject.className).toBe("Item"); - CustomObject = ParseObject.extend({ className: 'Test' }); - expect(CustomObject.className).toBe('Test'); + CustomObject = ParseObject.extend({ className: "Test" }); + expect(CustomObject.className).toBe("Test"); }); - it('can extend with user rewrite', () => { - const CustomObject = ParseObject.extend('User'); - expect(CustomObject.className).toBe('_User'); + it("can extend with user rewrite", () => { + const CustomObject = ParseObject.extend("User"); + expect(CustomObject.className).toBe("_User"); }); - it('can extend multiple subclasses', () => { - const CustomObject = ParseObject.extend('Item'); + it("can extend multiple subclasses", () => { + const CustomObject = ParseObject.extend("Item"); expect(() => { - new CustomObject({ 'invalid#name': 'bar' }); + new CustomObject({ "invalid#name": "bar" }); }).toThrow("Can't create an invalid Parse Object"); - const CustomUserObject = CustomObject.extend('User'); + const CustomUserObject = CustomObject.extend("User"); const CustomRewrite = CustomUserObject.extend(); - expect(CustomRewrite.className).toBe('_User'); + expect(CustomRewrite.className).toBe("_User"); }); }); -describe('ParseObject pin', () => { +describe("ParseObject pin", () => { beforeEach(() => { ParseObject.enableSingleInstance(); jest.clearAllMocks(); mockLocalDatastore.isEnabled = true; }); - it('can pin to default', async () => { - const object = new ParseObject('Item'); + it("can pin to default", async () => { + const object = new ParseObject("Item"); await object.pin(); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledWith(DEFAULT_PIN, [object]); + expect( + mockLocalDatastore._handlePinAllWithName + ).toHaveBeenCalledWith(DEFAULT_PIN, [object]); }); - it('can unPin to default', async () => { - const object = new ParseObject('Item'); + it("can unPin to default", async () => { + const object = new ParseObject("Item"); await object.unPin(); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledWith(DEFAULT_PIN, [object]); + expect( + mockLocalDatastore._handleUnPinAllWithName + ).toHaveBeenCalledWith(DEFAULT_PIN, [object]); }); - it('can pin to specific pin', async () => { - const object = new ParseObject('Item'); - await object.pinWithName('test_pin'); + it("can pin to specific pin", async () => { + const object = new ParseObject("Item"); + await object.pinWithName("test_pin"); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledWith('test_pin', [object]); + expect( + mockLocalDatastore._handlePinAllWithName + ).toHaveBeenCalledWith("test_pin", [object]); }); - it('can unPin to specific', async () => { - const object = new ParseObject('Item'); - await object.unPinWithName('test_pin'); + it("can unPin to specific", async () => { + const object = new ParseObject("Item"); + await object.unPinWithName("test_pin"); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledWith('test_pin', [object]); + expect( + mockLocalDatastore._handleUnPinAllWithName + ).toHaveBeenCalledWith("test_pin", [object]); }); - it('can check if pinned', async () => { - const object = new ParseObject('Item'); - object.id = '1234'; - mockLocalDatastore - .fromPinWithName + it("can check if pinned", async () => { + const object = new ParseObject("Item"); + object.id = "1234"; + mockLocalDatastore.fromPinWithName .mockImplementationOnce(() => { return [object._toFullJSON()]; }) @@ -3421,139 +3663,153 @@ describe('ParseObject pin', () => { expect(isPinned).toEqual(false); }); - it('can fetchFromLocalDatastore', async () => { - const object = new ParseObject('Item'); - object.id = '123'; - mockLocalDatastore - .getKeyForObject - .mockImplementationOnce(() => 'Item_123'); + it("can fetchFromLocalDatastore", async () => { + const object = new ParseObject("Item"); + object.id = "123"; + mockLocalDatastore.getKeyForObject.mockImplementationOnce(() => "Item_123"); - mockLocalDatastore - ._serializeObject - .mockImplementationOnce(() => object._toFullJSON()); + mockLocalDatastore._serializeObject.mockImplementationOnce(() => + object._toFullJSON() + ); await object.fetchFromLocalDatastore(); expect(mockLocalDatastore._serializeObject).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._serializeObject).toHaveBeenCalledWith('Item_123'); + expect(mockLocalDatastore._serializeObject).toHaveBeenCalledWith( + "Item_123" + ); }); - it('cannot fetchFromLocalDatastore if unsaved', async () => { + it("cannot fetchFromLocalDatastore if unsaved", async () => { try { - const object = new ParseObject('Item'); + const object = new ParseObject("Item"); await object.fetchFromLocalDatastore(); } catch (e) { - expect(e.message).toBe('Cannot fetch an unsaved ParseObject'); + expect(e.message).toBe("Cannot fetch an unsaved ParseObject"); } }); - it('can pinAll', async () => { - const obj1 = new ParseObject('Item'); - const obj2 = new ParseObject('Item'); + it("can pinAll", async () => { + const obj1 = new ParseObject("Item"); + 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 () => { - const obj1 = new ParseObject('Item'); - const obj2 = new ParseObject('Item'); + it("can unPinAll", async () => { + const obj1 = new ParseObject("Item"); + 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 () => { + it("can unPinAllObjects", async () => { await ParseObject.unPinAllObjects(); expect(mockLocalDatastore.unPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([DEFAULT_PIN]); + expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([ + DEFAULT_PIN, + ]); }); - it('can unPinAllObjectsWithName', async () => { - await ParseObject.unPinAllObjectsWithName('123'); + it("can unPinAllObjectsWithName", async () => { + await ParseObject.unPinAllObjectsWithName("123"); expect(mockLocalDatastore.unPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([PIN_PREFIX + '123']); + expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([ + PIN_PREFIX + "123", + ]); }); - it('cannot pin when localDatastore disabled', async () => { + it("cannot pin when localDatastore disabled", async () => { mockLocalDatastore.isEnabled = false; - const name = 'test_pin'; - const obj = new ParseObject('Item'); + const name = "test_pin"; + const obj = new ParseObject("Item"); try { await obj.pin(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await obj.unPin(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await obj.isPinned(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await obj.pinWithName(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await obj.unPinWithName(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await obj.fetchFromLocalDatastore(); } catch (error) { - expect(error.message).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error.message).toBe( + "Parse.enableLocalDatastore() must be called first" + ); } try { await ParseObject.pinAll([obj]); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await ParseObject.unPinAll([obj]); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await ParseObject.pinAllWithName(name, [obj]); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await ParseObject.unPinAllWithName(name, [obj]); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await ParseObject.unPinAllObjects(); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + expect(error).toBe("Parse.enableLocalDatastore() must be called first"); } try { await ParseObject.unPinAllObjectsWithName(name); } catch (error) { - expect(error).toBe('Parse.enableLocalDatastore() must be called first'); + 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) => { + const p = new ParseObject("Person"); + p.save(null, { cascadeSave: false }).then((obj) => { expect(obj).toBe(p); - expect(obj.id).toBe('P5'); + expect(obj.id).toBe("P5"); done(); }); - }) + }); }); diff --git a/src/__tests__/ParseOp-test.js b/src/__tests__/ParseOp-test.js index bbbf135cf..16097a8e5 100644 --- a/src/__tests__/ParseOp-test.js +++ b/src/__tests__/ParseOp-test.js @@ -7,38 +7,38 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../arrayContainsObject'); -jest.dontMock('../encode'); -jest.dontMock('../decode'); -jest.dontMock('../ParseOp'); -jest.dontMock('../unique'); +jest.dontMock("../arrayContainsObject"); +jest.dontMock("../encode"); +jest.dontMock("../decode"); +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++; + 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() {}; -jest.setMock('../ParseObject', mockObject); +}; +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); +}; +jest.setMock("../ParseRelation", mockRelation); -const ParseRelation = require('../ParseRelation'); -const ParseObject = require('../ParseObject'); -const ParseOp = require('../ParseOp'); +const ParseRelation = require("../ParseRelation"); +const ParseObject = require("../ParseObject"); +const ParseOp = require("../ParseOp"); const { Op, SetOp, @@ -51,8 +51,8 @@ const { opFromJSON, } = ParseOp; -describe('ParseOp', () => { - it('base class', () => { +describe("ParseOp", () => { + it("base class", () => { const op = new Op(); expect(op.applyTo instanceof Function).toBe(true); expect(op.mergeWith instanceof Function).toBe(true); @@ -61,11 +61,11 @@ describe('ParseOp', () => { expect(op.mergeWith()).toBeUndefined(); expect(op.toJSON()).toBeUndefined(); expect(opFromJSON({})).toBe(null); - expect(opFromJSON({ __op: 'Unknown' })).toBe(null); + expect(opFromJSON({ __op: "Unknown" })).toBe(null); expect(opFromJSON(op.toJSON())).toBe(null); }); - it('is extended by all Ops', () => { + it("is extended by all Ops", () => { expect(new SetOp(1) instanceof Op).toBe(true); expect(new UnsetOp() instanceof Op).toBe(true); expect(new IncrementOp(1) instanceof Op).toBe(true); @@ -74,13 +74,13 @@ describe('ParseOp', () => { expect(new RemoveOp(1) instanceof Op).toBe(true); }); - it('can create and apply Set Ops', () => { + it("can create and apply Set Ops", () => { const set = new SetOp(14); expect(set.applyTo(null)).toBe(14); expect(set.applyTo(undefined)).toBe(14); expect(set.applyTo(41)).toBe(14); - expect(set.applyTo('14')).toBe(14); + expect(set.applyTo("14")).toBe(14); // SetOp overrides all expect(set.mergeWith(new SetOp(12))._value).toBe(14); @@ -93,13 +93,13 @@ describe('ParseOp', () => { expect(set.toJSON()).toBe(14); }); - it('can create and apply Unset Ops', () => { + it("can create and apply Unset Ops", () => { const unset = new UnsetOp(); expect(unset.applyTo(null)).toBe(undefined); expect(unset.applyTo(undefined)).toBe(undefined); expect(unset.applyTo(14)).toBe(undefined); - expect(unset.applyTo('14')).toBe(undefined); + expect(unset.applyTo("14")).toBe(undefined); // UnsetOp overrides all expect(unset.mergeWith(new SetOp(12)) instanceof UnsetOp).toBe(true); @@ -109,23 +109,23 @@ describe('ParseOp', () => { expect(unset.mergeWith(new AddUniqueOp(1)) instanceof UnsetOp).toBe(true); expect(unset.mergeWith(new RemoveOp(1)) instanceof UnsetOp).toBe(true); - expect(unset.toJSON()).toEqual({ __op: 'Delete' }); + expect(unset.toJSON()).toEqual({ __op: "Delete" }); expect(opFromJSON(unset.toJSON())).toEqual(unset); }); - 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.' - ); + 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."); const inc = new IncrementOp(1); expect(inc.applyTo.bind(inc, null)).toThrow( - 'Cannot increment a non-numeric value.' + "Cannot increment a non-numeric value." ); - expect(inc.applyTo.bind(inc, 'abc')).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); @@ -134,8 +134,8 @@ describe('ParseOp', () => { expect(bigInc.applyTo(-98)).toBe(1); expect(bigInc.applyTo()).toBe(99); - expect(inc.toJSON()).toEqual({ __op: 'Increment', amount: 1 }); - expect(bigInc.toJSON()).toEqual({ __op: 'Increment', amount: 99 }); + expect(inc.toJSON()).toEqual({ __op: "Increment", amount: 1 }); + expect(bigInc.toJSON()).toEqual({ __op: "Increment", amount: 99 }); expect(opFromJSON(bigInc.toJSON())).toEqual(bigInc); let merge = inc.mergeWith(); @@ -155,74 +155,77 @@ describe('ParseOp', () => { expect(merge._amount).toBe(100); expect(inc.mergeWith.bind(inc, new AddOp(1))).toThrow( - 'Cannot merge Increment Op with the previous Op' + "Cannot merge Increment Op with the previous Op" ); expect(inc.mergeWith.bind(inc, new AddUniqueOp(1))).toThrow( - 'Cannot merge Increment Op with the previous Op' + "Cannot merge Increment Op with the previous Op" ); expect(inc.mergeWith.bind(inc, new RemoveOp(1))).toThrow( - 'Cannot merge Increment Op with the previous Op' + "Cannot merge Increment Op with the previous Op" ); }); - it('can create and apply Add Ops', () => { - const add = new AddOp('element'); + it("can create and apply Add Ops", () => { + const add = new AddOp("element"); - 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(add.applyTo([12])).toEqual([12, 'element']); + 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(add.applyTo([12])).toEqual([12, "element"]); - expect(add.toJSON()).toEqual({ __op: 'Add', objects: ['element'] }); + expect(add.toJSON()).toEqual({ __op: "Add", objects: ["element"] }); expect(opFromJSON(add.toJSON())).toEqual(add); const addMany = new AddOp([1, 2, 2, 3, 4, 5]); 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); - expect(merge._value).toEqual(['element']); + expect(merge._value).toEqual(["element"]); - merge = add.mergeWith(new SetOp(['an'])); + merge = add.mergeWith(new SetOp(["an"])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(['an', 'element']); + expect(merge._value).toEqual(["an", "element"]); - merge = add.mergeWith(new UnsetOp(['an'])); + merge = add.mergeWith(new UnsetOp(["an"])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(['element']); + expect(merge._value).toEqual(["element"]); merge = add.mergeWith(addMany); expect(merge instanceof AddOp).toBe(true); - expect(merge._value).toEqual([1, 2, 2, 3, 4, 5, 'element']); + expect(merge._value).toEqual([1, 2, 2, 3, 4, 5, "element"]); expect(add.mergeWith.bind(add, new IncrementOp(1))).toThrow( - 'Cannot merge Add Op with the previous Op' + "Cannot merge Add Op with the previous Op" ); expect(add.mergeWith.bind(add, new AddUniqueOp(1))).toThrow( - 'Cannot merge Add Op with the previous Op' + "Cannot merge Add Op with the previous Op" ); expect(add.mergeWith.bind(add, new RemoveOp(1))).toThrow( - 'Cannot merge Add Op with the previous Op' + "Cannot merge Add Op with the previous Op" ); }); - it('can create and apply AddUnique Ops', () => { - const add = new AddUniqueOp('element'); + it("can create and apply AddUnique Ops", () => { + const add = new AddUniqueOp("element"); - 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(add.applyTo([12])).toEqual([12, 'element']); - expect(add.applyTo([12, 'element'])).toEqual([12, 'element']); + 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(add.applyTo([12])).toEqual([12, "element"]); + expect(add.applyTo([12, "element"])).toEqual([12, "element"]); - expect(add.toJSON()).toEqual({ __op: 'AddUnique', objects: ['element'] }); + expect(add.toJSON()).toEqual({ __op: "AddUnique", objects: ["element"] }); expect(opFromJSON(add.toJSON())).toEqual(add); const addMany = new AddUniqueOp([1, 2, 2, 3, 4, 5]); @@ -232,72 +235,77 @@ describe('ParseOp', () => { expect(addMany.applyTo([-2, 1, 4, 0])).toEqual([-2, 1, 4, 0, 2, 3, 5]); expect(addMany.toJSON()).toEqual({ - __op: 'AddUnique', - objects: [1, 2, 3, 4, 5] + __op: "AddUnique", + objects: [1, 2, 3, 4, 5], }); let merge = add.mergeWith(null); expect(merge instanceof AddUniqueOp).toBe(true); - expect(merge._value).toEqual(['element']); + expect(merge._value).toEqual(["element"]); - merge = add.mergeWith(new SetOp(['an', 'element'])); + merge = add.mergeWith(new SetOp(["an", "element"])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(['an', 'element']); + expect(merge._value).toEqual(["an", "element"]); - merge = add.mergeWith(new UnsetOp(['an'])); + merge = add.mergeWith(new UnsetOp(["an"])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(['element']); + 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']); + expect(merge._value).toEqual([1, 2, "element", 3, "an"]); expect(add.mergeWith.bind(add, new IncrementOp(1))).toThrow( - 'Cannot merge AddUnique Op with the previous Op' + "Cannot merge AddUnique Op with the previous Op" ); expect(add.mergeWith.bind(add, new AddOp(1))).toThrow( - 'Cannot merge AddUnique Op with the previous Op' + "Cannot merge AddUnique Op with the previous Op" ); expect(add.mergeWith.bind(add, new RemoveOp(1))).toThrow( - 'Cannot merge AddUnique Op with the previous Op' + "Cannot merge AddUnique Op with the previous Op" ); - let addObjects = new AddUniqueOp(new ParseObject('Item', 'i2')); - 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'), + let addObjects = new AddUniqueOp(new ParseObject("Item", "i2")); + 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([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i3'), - new ParseObject('Item', 'i2'), + addObjects = new AddUniqueOp(new ParseObject("Item", "i2")); + expect( + addObjects.applyTo([ + new ParseObject("Item", "i1"), + new ParseObject("Item", "i3"), + ]) + ).toEqual([ + new ParseObject("Item", "i1"), + new ParseObject("Item", "i3"), + new ParseObject("Item", "i2"), ]); }); - it('can create and apply Remove Ops', () => { - const rem = new RemoveOp('element'); + it("can create and apply Remove Ops", () => { + const rem = new RemoveOp("element"); 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]); + expect(rem.applyTo([12, "element"])).toEqual([12]); + expect(rem.applyTo(["element", 12, "element", "element"])).toEqual([12]); - expect(rem.toJSON()).toEqual({ __op: 'Remove', objects: ['element'] }); + expect(rem.toJSON()).toEqual({ __op: "Remove", objects: ["element"] }); expect(opFromJSON(rem.toJSON())).toEqual(rem); const removeMany = new RemoveOp([1, 2, 2, 3, 4, 5]); @@ -305,19 +313,19 @@ describe('ParseOp', () => { expect(removeMany.applyTo([-2, 1, 4, 0])).toEqual([-2, 0]); expect(removeMany.toJSON()).toEqual({ - __op: 'Remove', - objects: [1, 2, 3, 4, 5] + __op: "Remove", + objects: [1, 2, 3, 4, 5], }); let merge = rem.mergeWith(null); expect(merge instanceof RemoveOp).toBe(true); - expect(merge._value).toEqual(['element']); + expect(merge._value).toEqual(["element"]); - merge = rem.mergeWith(new SetOp(['an', 'element'])); + merge = rem.mergeWith(new SetOp(["an", "element"])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(['an']); + expect(merge._value).toEqual(["an"]); - merge = rem.mergeWith(new UnsetOp(['an'])); + merge = rem.mergeWith(new UnsetOp(["an"])); expect(merge instanceof UnsetOp).toBe(true); expect(merge._value).toEqual(undefined); @@ -326,38 +334,36 @@ describe('ParseOp', () => { expect(merge._value).toEqual([2, 4, 1, 3]); expect(rem.mergeWith.bind(rem, new IncrementOp(1))).toThrow( - 'Cannot merge Remove Op with the previous Op' + "Cannot merge Remove Op with the previous Op" ); - 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'), - ]); + 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")]); const merged = removeObjects.mergeWith(previousOp); expect(merged._value).toEqual([ - new ParseObject('Item', 'i5'), - new ParseObject('Item', 'i2'), + new ParseObject("Item", "i5"), + new ParseObject("Item", "i2"), ]); }); - it('can create and apply Relation Ops', () => { + it("can create and apply Relation Ops", () => { let r = new RelationOp(); expect(r.relationsToAdd).toBe(undefined); expect(r.relationsToRemove).toBe(undefined); @@ -366,125 +372,135 @@ describe('ParseOp', () => { expect(r.relationsToAdd).toEqual([]); expect(r.relationsToRemove).toEqual([]); - expect(function() { - new RelationOp([new ParseObject('Item')], []); + expect(function () { + new RelationOp([new ParseObject("Item")], []); }).toThrow( - 'You cannot add or remove an unsaved Parse Object from a relation' + "You cannot add or remove an unsaved Parse Object from a relation" ); - expect(function() { - const a = new ParseObject('Item'); - a.id = 'I1'; - const b = new ParseObject('Delivery'); - b.id = 'D1'; + 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.' + "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' + const o = new ParseObject("Item"); + o.id = "I1"; + const o2 = new ParseObject("Item"); + o2.id = "I2"; r = new RelationOp([o, o, o2], []); - expect(r.relationsToAdd).toEqual(['I1', 'I2']); + expect(r.relationsToAdd).toEqual(["I1", "I2"]); expect(r.relationsToRemove).toEqual([]); - expect(r._targetClassName).toBe('Item'); + expect(r._targetClassName).toBe("Item"); expect(r.toJSON()).toEqual({ - __op: 'AddRelation', + __op: "AddRelation", objects: [ - { __type: 'Pointer', objectId: 'I1', className: 'Item' }, - { __type: 'Pointer', objectId: 'I2', className: 'Item' } - ] + { __type: "Pointer", objectId: "I1", className: "Item" }, + { __type: "Pointer", objectId: "I2", className: "Item" }, + ], }); expect(opFromJSON(r.toJSON())).toEqual(r); - const o3 = new ParseObject('Item'); - o3.id = 'I3'; + const o3 = new ParseObject("Item"); + o3.id = "I3"; const r2 = new RelationOp([], [o3, o, o]); expect(r2.relationsToAdd).toEqual([]); - expect(r2.relationsToRemove).toEqual(['I3', 'I1']); + expect(r2.relationsToRemove).toEqual(["I3", "I1"]); expect(r2.toJSON()).toEqual({ - __op: 'RemoveRelation', + __op: "RemoveRelation", objects: [ - { __type: 'Pointer', objectId: 'I3', className: 'Item' }, - { __type: 'Pointer', objectId: 'I1', className: 'Item' } - ] + { __type: "Pointer", objectId: "I3", className: "Item" }, + { __type: "Pointer", objectId: "I1", className: "Item" }, + ], }); expect(opFromJSON(r2.toJSON())).toEqual(r2); - const rel = r.applyTo(undefined, { className: 'Delivery', id: 'D3' }, 'shipments'); - expect(rel.targetClassName).toBe('Item'); - expect(r2.applyTo(rel, { className: 'Delivery', id: 'D3' })).toBe(rel); + const rel = r.applyTo( + undefined, + { className: "Delivery", id: "D3" }, + "shipments" + ); + expect(rel.targetClassName).toBe("Item"); + expect(r2.applyTo(rel, { className: "Delivery", id: "D3" })).toBe(rel); - const relLocal = r.applyTo(undefined, { className: 'Delivery', id: 'localD4' }, 'shipments'); - expect(relLocal.parent._localId).toBe('localD4'); + const relLocal = r.applyTo( + undefined, + { className: "Delivery", id: "localD4" }, + "shipments" + ); + expect(relLocal.parent._localId).toBe("localD4"); - expect(r.applyTo.bind(r, 'string')).toThrow( - 'Relation cannot be applied to a non-relation field' + expect(r.applyTo.bind(r, "string")).toThrow( + "Relation cannot be applied to a non-relation field" ); expect(r.applyTo.bind(r)).toThrow( - 'Cannot apply a RelationOp without either a previous value, or an object and a key' + "Cannot apply a RelationOp without either a previous value, or an object and a key" ); - const p = new ParseObject('Person'); - p.id = 'P4'; + 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'); + r3.applyTo(noRelation, { className: "Delivery", id: "D3" }, "packages"); expect(noRelation.targetClassName).toEqual(r3._targetClassName); expect(r.mergeWith(null)).toBe(r); expect(r.mergeWith.bind(r, new UnsetOp())).toThrow( - 'You cannot modify a relation after deleting it.' + "You cannot modify a relation after deleting it." ); expect(r.mergeWith.bind(r, new SetOp(12))).toThrow( - 'Cannot merge Relation Op with the previous Op' + "Cannot merge Relation Op with the previous Op" ); const merged = r2.mergeWith(r); expect(merged.toJSON()).toEqual({ - __op: 'Batch', + __op: "Batch", ops: [ { - __op: 'AddRelation', - objects: [ { __type: 'Pointer', objectId: 'I2', className: 'Item' } ] - }, { - __op: 'RemoveRelation', + __op: "AddRelation", + 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: "I3", className: "Item" }, + { __type: "Pointer", objectId: "I1", className: "Item" }, + ], + }, + ], }); expect(opFromJSON(merged.toJSON())).toEqual(merged); }); - it('can merge Relation Op with the previous Op', () => { + it("can merge Relation Op with the previous Op", () => { const r = new RelationOp(); const relation = new ParseRelation(null, null); const set = new SetOp(relation); expect(r.mergeWith(set)).toEqual(r); - const a = new ParseObject('Item'); - a.id = 'I1'; - const b = new ParseObject('Item'); - b.id = 'D1'; + const a = new ParseObject("Item"); + a.id = "I1"; + const b = new ParseObject("Item"); + b.id = "D1"; const r1 = new RelationOp([a, b], []); const r2 = new RelationOp([], [b]); expect(() => { - r.mergeWith(r1) - }).toThrow('Related object must be of class Item, but null was passed in.'); + 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])); }); - it('opFromJSON Relation', () => { + it("opFromJSON Relation", () => { const r = new RelationOp([], []); - expect(opFromJSON({ __op: 'AddRelation', objects: '' })).toEqual(r); - expect(opFromJSON({ __op: 'RemoveRelation', objects: '' })).toEqual(r); + expect(opFromJSON({ __op: "AddRelation", objects: "" })).toEqual(r); + expect(opFromJSON({ __op: "RemoveRelation", objects: "" })).toEqual(r); }); }); diff --git a/src/__tests__/ParsePolygon-test.js b/src/__tests__/ParsePolygon-test.js index 22b6c29cb..29503b476 100644 --- a/src/__tests__/ParsePolygon-test.js +++ b/src/__tests__/ParsePolygon-test.js @@ -1,30 +1,42 @@ jest.autoMockOff(); -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParsePolygon = require('../ParsePolygon').default; - -const points = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; - -describe('Polygon', () => { - it('can initialize with points', () => { +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParsePolygon = require("../ParsePolygon").default; + +const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], +]; + +describe("Polygon", () => { + it("can initialize with points", () => { const polygon = new ParsePolygon(points); expect(polygon.coordinates).toEqual(points); }); - it('can initialize with geopoints', () => { + it("can initialize with geopoints", () => { const geopoints = [ new ParseGeoPoint(0, 0), 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]]; + it("can set points", () => { + const newPoints = [ + [0, 0], + [0, 10], + [10, 10], + [10, 0], + [0, 0], + ]; const polygon = new ParsePolygon(points); expect(polygon.coordinates).toEqual(points); @@ -33,15 +45,15 @@ describe('Polygon', () => { expect(polygon.coordinates).toEqual(newPoints); }); - it('toJSON', () => { + it("toJSON", () => { const polygon = new ParsePolygon(points); expect(polygon.toJSON()).toEqual({ - __type: 'Polygon', + __type: "Polygon", coordinates: points, }); }); - it('equals', () => { + it("equals", () => { const polygon1 = new ParsePolygon(points); const polygon2 = new ParsePolygon(points); const geopoint = new ParseGeoPoint(0, 0); @@ -49,31 +61,37 @@ 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); }); - it('containsPoint', () => { + 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); }); - it('throws error on invalid input', () => { + it("throws error on invalid input", () => { expect(() => { - new ParsePolygon() - }).toThrow('Coordinates must be an Array'); + new ParsePolygon(); + }).toThrow("Coordinates must be an Array"); expect(() => { - new ParsePolygon([]) - }).toThrow('Polygon must have at least 3 GeoPoints or Points'); + new ParsePolygon([]); + }).toThrow("Polygon must have at least 3 GeoPoints or Points"); expect(() => { - new ParsePolygon([1, 2, 3]) - }).toThrow('Coordinates must be an Array of GeoPoints or Points'); + 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..dc9ddca21 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -7,53 +7,53 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../encode'); -jest.dontMock('../decode'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseQuery'); -jest.dontMock('../promiseUtils'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../UniqueInstanceStateController'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../LocalDatastore'); -jest.dontMock('../OfflineQuery'); -jest.dontMock('../LiveQuerySubscription'); - -jest.mock('uuid/v4', () => { +jest.dontMock("../CoreManager"); +jest.dontMock("../encode"); +jest.dontMock("../decode"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseQuery"); +jest.dontMock("../promiseUtils"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../LocalDatastore"); +jest.dontMock("../OfflineQuery"); +jest.dontMock("../LiveQuerySubscription"); + +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) { - if (attr !== 'className' && attr !== '__type' && attr !== 'objectId') { + if (attr !== "className" && attr !== "__type" && attr !== "objectId") { o.attributes[attr] = json[attr]; } } return o; }; -jest.setMock('../ParseObject', mockObject); +jest.setMock("../ParseObject", mockObject); const mockLocalDatastore = { _serializeObjectsFromPinName: jest.fn(), checkIfEnabled: jest.fn(), }; -jest.setMock('../LocalDatastore', mockLocalDatastore); +jest.setMock("../LocalDatastore", mockLocalDatastore); -let CoreManager = require('../CoreManager'); -const ParseError = require('../ParseError').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -let ParseObject = require('../ParseObject'); -let ParseQuery = require('../ParseQuery').default; -const LiveQuerySubscription = require('../LiveQuerySubscription').default; +let CoreManager = require("../CoreManager"); +const ParseError = require("../ParseError").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +let ParseObject = require("../ParseObject"); +let ParseQuery = require("../ParseQuery").default; +const LiveQuerySubscription = require("../LiveQuerySubscription").default; const MockRESTController = { request: jest.fn(), @@ -62,963 +62,958 @@ const MockRESTController = { const QueryController = CoreManager.getQueryController(); -import { DEFAULT_PIN } from '../LocalDatastoreUtils'; +import { DEFAULT_PIN } from "../LocalDatastoreUtils"; -describe('ParseQuery', () => { +describe("ParseQuery", () => { beforeEach(() => { CoreManager.setQueryController(QueryController); CoreManager.setRESTController(MockRESTController); }); - it('can be constructed from a class name', () => { - const q = new ParseQuery('Item'); - expect(q.className).toBe('Item'); + it("can be constructed from a class name", () => { + const q = new ParseQuery("Item"); + expect(q.className).toBe("Item"); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); - it('can be constructed from a ParseObject', () => { - const item = new ParseObject('Item'); + it("can be constructed from a ParseObject", () => { + const item = new ParseObject("Item"); const q2 = new ParseQuery(item); - expect(q2.className).toBe('Item'); + expect(q2.className).toBe("Item"); expect(q2.toJSON()).toEqual({ - where: {} + where: {}, }); }); - it('can be constructed from a function constructor', () => { + it("can be constructed from a function constructor", () => { function ObjectFunction() { - this.className = 'Item'; + this.className = "Item"; } const q = new ParseQuery(ObjectFunction); - expect(q.className).toBe('Item'); + expect(q.className).toBe("Item"); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); - it('can be constructed from a function prototype', () => { + it("can be constructed from a function prototype", () => { function ObjectFunction() {} - ObjectFunction.className = 'Item'; + ObjectFunction.className = "Item"; const q = new ParseQuery(ObjectFunction); - expect(q.className).toBe('Item'); + expect(q.className).toBe("Item"); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); - it('throws when created with invalid data', () => { - expect(function() { + it("throws when created with invalid data", () => { + expect(function () { new ParseQuery(); }).toThrow( - 'A ParseQuery must be constructed with a ParseObject or class name.' + "A ParseQuery must be constructed with a ParseObject or class name." ); }); - it('can generate equality queries', () => { - const q = new ParseQuery('Item'); - q.equalTo('size', 'medium'); + it("can generate equality queries", () => { + const q = new ParseQuery("Item"); + q.equalTo("size", "medium"); expect(q.toJSON()).toEqual({ where: { - size: 'medium' - } + size: "medium", + }, }); // Overrides old constraint - q.equalTo('size', 'small'); + q.equalTo("size", "small"); expect(q.toJSON()).toEqual({ where: { - size: 'small' - } + size: "small", + }, }); // equalTo('key', undefined) resolves to 'does not exist' - q.equalTo('size'); + q.equalTo("size"); expect(q.toJSON()).toEqual({ where: { size: { - $exists: false - } - } + $exists: false, + }, + }, }); - const size = 'medium'; + const size = "medium"; const stock = true; q.equalTo({ size, stock }); expect(q.toJSON()).toEqual({ where: { - size: 'medium', + size: "medium", stock: true, - } + }, }); }); - it('can generate inequality queries', () => { - const q = new ParseQuery('Item'); - q.notEqualTo('size', 'small'); + it("can generate inequality queries", () => { + const q = new ParseQuery("Item"); + q.notEqualTo("size", "small"); expect(q.toJSON()).toEqual({ where: { size: { - $ne: 'small' - } - } + $ne: "small", + }, + }, }); - q.notEqualTo('size', 'medium'); + q.notEqualTo("size", "medium"); expect(q.toJSON()).toEqual({ where: { size: { - $ne: 'medium' - } - } + $ne: "medium", + }, + }, }); - const size = 'medium'; + const size = "medium"; const stock = true; q.notEqualTo({ size, stock }); expect(q.toJSON()).toEqual({ where: { size: { - $ne: 'medium', + $ne: "medium", }, stock: { $ne: true, - } - } + }, + }, }); }); - it('can generate less-than queries', () => { - const q = new ParseQuery('Item'); - q.lessThan('inStock', 10); + it("can generate less-than queries", () => { + const q = new ParseQuery("Item"); + q.lessThan("inStock", 10); expect(q.toJSON()).toEqual({ where: { inStock: { - $lt: 10 - } - } + $lt: 10, + }, + }, }); - q.lessThan('inStock', 4); + q.lessThan("inStock", 4); expect(q.toJSON()).toEqual({ where: { inStock: { - $lt: 4 - } - } + $lt: 4, + }, + }, }); }); - it('can generate less-than-or-equal-to queries', () => { - const q = new ParseQuery('Item'); - q.lessThanOrEqualTo('inStock', 10); + it("can generate less-than-or-equal-to queries", () => { + const q = new ParseQuery("Item"); + q.lessThanOrEqualTo("inStock", 10); expect(q.toJSON()).toEqual({ where: { inStock: { - $lte: 10 - } - } + $lte: 10, + }, + }, }); - q.lessThanOrEqualTo('inStock', 4); + q.lessThanOrEqualTo("inStock", 4); expect(q.toJSON()).toEqual({ where: { inStock: { - $lte: 4 - } - } + $lte: 4, + }, + }, }); }); - it('can generate greater-than queries', () => { - const q = new ParseQuery('Item'); - q.greaterThan('inStock', 0); + it("can generate greater-than queries", () => { + const q = new ParseQuery("Item"); + q.greaterThan("inStock", 0); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } - } + $gt: 0, + }, + }, }); - q.greaterThan('inStock', 100); + q.greaterThan("inStock", 100); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 100 - } - } + $gt: 100, + }, + }, }); }); - it('can generate greater-than-or-equal-to queries', () => { - const q = new ParseQuery('Item'); - q.greaterThanOrEqualTo('inStock', 0); + it("can generate greater-than-or-equal-to queries", () => { + const q = new ParseQuery("Item"); + q.greaterThanOrEqualTo("inStock", 0); expect(q.toJSON()).toEqual({ where: { inStock: { - $gte: 0 - } - } + $gte: 0, + }, + }, }); - q.greaterThanOrEqualTo('inStock', 100); + q.greaterThanOrEqualTo("inStock", 100); expect(q.toJSON()).toEqual({ where: { inStock: { - $gte: 100 - } - } + $gte: 100, + }, + }, }); }); - it('can generate contained-in queries', () => { - const q = new ParseQuery('Item'); - q.containedIn('size', ['small', 'medium']); + it("can generate contained-in queries", () => { + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]); expect(q.toJSON()).toEqual({ where: { size: { - $in: ['small', 'medium'] - } - } + $in: ["small", "medium"], + }, + }, }); - q.containedIn('size', ['small', 'medium', 'large']); + q.containedIn("size", ["small", "medium", "large"]); expect(q.toJSON()).toEqual({ where: { size: { - $in: ['small', 'medium', 'large'] - } - } + $in: ["small", "medium", "large"], + }, + }, }); }); - it('can generate not-contained-in queries', () => { - const q = new ParseQuery('Item'); - q.notContainedIn('size', ['small', 'medium']); + it("can generate not-contained-in queries", () => { + const q = new ParseQuery("Item"); + q.notContainedIn("size", ["small", "medium"]); expect(q.toJSON()).toEqual({ where: { size: { - $nin: ['small', 'medium'] - } - } + $nin: ["small", "medium"], + }, + }, }); - q.notContainedIn('size', ['small', 'large']); + q.notContainedIn("size", ["small", "large"]); expect(q.toJSON()).toEqual({ where: { size: { - $nin: ['small', 'large'] - } - } + $nin: ["small", "large"], + }, + }, }); }); - it('can generate contains-all queries', () => { - const q = new ParseQuery('Item'); - q.containsAll('tags', ['hot', 'sold-out']); + it("can generate contains-all queries", () => { + const q = new ParseQuery("Item"); + q.containsAll("tags", ["hot", "sold-out"]); expect(q.toJSON()).toEqual({ where: { tags: { - $all: ['hot', 'sold-out'] - } - } + $all: ["hot", "sold-out"], + }, + }, }); - q.containsAll('tags', ['sale', 'new']); + q.containsAll("tags", ["sale", "new"]); expect(q.toJSON()).toEqual({ where: { tags: { - $all: ['sale', 'new'] - } - } + $all: ["sale", "new"], + }, + }, }); }); - it('can generate containedBy queries', () => { - const q = new ParseQuery('Item'); - q.containedBy('tags', ['hot', 'sold-out']); + it("can generate containedBy queries", () => { + const q = new ParseQuery("Item"); + q.containedBy("tags", ["hot", "sold-out"]); expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ['hot', 'sold-out'] + $containedBy: ["hot", "sold-out"], }, }, }); - q.containedBy('tags', ['sale', 'new']); + q.containedBy("tags", ["sale", "new"]); expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ['sale', 'new'] + $containedBy: ["sale", "new"], }, }, }); }); - it('can generate contains-all-starting-with queries', () => { - const q = new ParseQuery('Item'); - q.containsAllStartingWith('tags', ['ho', 'out']); + it("can generate contains-all-starting-with queries", () => { + const q = new ParseQuery("Item"); + q.containsAllStartingWith("tags", ["ho", "out"]); 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']); + 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'); + q.containsAllStartingWith("tags", "noArray"); expect(q.toJSON()).toEqual({ where: { tags: { - $all: [ - { $regex: '^\\QnoArray\\E' }, - ] - } - } + $all: [{ $regex: "^\\QnoArray\\E" }], + }, + }, }); }); - it('can generate exists queries', () => { - const q = new ParseQuery('Item'); - q.exists('name'); + it("can generate exists queries", () => { + const q = new ParseQuery("Item"); + q.exists("name"); expect(q.toJSON()).toEqual({ where: { name: { - $exists: true - } - } + $exists: true, + }, + }, }); }); - it('can generate does-not-exist queries', () => { - const q = new ParseQuery('Item'); - q.doesNotExist('name'); + it("can generate does-not-exist queries", () => { + const q = new ParseQuery("Item"); + q.doesNotExist("name"); expect(q.toJSON()).toEqual({ where: { name: { - $exists: false - } - } + $exists: false, + }, + }, }); }); - it('can generate RegExp queries', () => { - const q = new ParseQuery('Item'); - q.matches('name', /ing$/); + it("can generate RegExp queries", () => { + const q = new ParseQuery("Item"); + q.matches("name", /ing$/); expect(q.toJSON()).toEqual({ where: { name: { - $regex: 'ing$' - } - } + $regex: "ing$", + }, + }, }); - q.matches('name', /\bor\b/, 'i'); + q.matches("name", /\bor\b/, "i"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\bor\\b', - $options: 'i' - } - } + $regex: "\\bor\\b", + $options: "i", + }, + }, }); - q.matches('name', /\bor\b/i); + q.matches("name", /\bor\b/i); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\bor\\b', - $options: 'i' - } - } + $regex: "\\bor\\b", + $options: "i", + }, + }, }); - q.matches('name', /\bor\b/im); + q.matches("name", /\bor\b/im); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\bor\\b', - $options: 'im' - } - } + $regex: "\\bor\\b", + $options: "im", + }, + }, }); }); - it('can generate queries that match results from other queries', () => { - const q1 = new ParseQuery('Item'); - q1.equalTo('inStock', 0); + it("can generate queries that match results from other queries", () => { + const q1 = new ParseQuery("Item"); + q1.equalTo("inStock", 0); - const q2 = new ParseQuery('Purchase'); - q2.matchesQuery('item', q1); + const q2 = new ParseQuery("Purchase"); + q2.matchesQuery("item", q1); expect(q2.toJSON()).toEqual({ where: { item: { $inQuery: { - className: 'Item', + className: "Item", where: { - inStock: 0 - } - } - } - } + inStock: 0, + }, + }, + }, + }, }); }); - it('can generate queries that don\'t match results from other queries', () => { - const q1 = new ParseQuery('Item'); - q1.equalTo('inStock', 0); + it("can generate queries that don't match results from other queries", () => { + const q1 = new ParseQuery("Item"); + q1.equalTo("inStock", 0); - const q2 = new ParseQuery('Purchase'); - q2.doesNotMatchQuery('item', q1); + const q2 = new ParseQuery("Purchase"); + q2.doesNotMatchQuery("item", q1); expect(q2.toJSON()).toEqual({ where: { item: { $notInQuery: { - className: 'Item', + className: "Item", where: { - inStock: 0 - } - } - } - } + inStock: 0, + }, + }, + }, + }, }); }); - it('can generate queries that match keys from other queries', () => { - const q1 = new ParseQuery('Item'); - q1.equalTo('inStock', 0); + it("can generate queries that match keys from other queries", () => { + const q1 = new ParseQuery("Item"); + q1.equalTo("inStock", 0); - const q2 = new ParseQuery('Review'); - q2.matchesKeyInQuery('itemName', 'name', q1); + const q2 = new ParseQuery("Review"); + q2.matchesKeyInQuery("itemName", "name", q1); expect(q2.toJSON()).toEqual({ where: { itemName: { $select: { - key: 'name', + key: "name", query: { - className: 'Item', + className: "Item", where: { - inStock: 0 - } - } - } - } - } + inStock: 0, + }, + }, + }, + }, + }, }); }); - it('can generate queries that don\'t match keys from other queries', () => { - const q1 = new ParseQuery('Item'); - q1.equalTo('inStock', 0); + it("can generate queries that don't match keys from other queries", () => { + const q1 = new ParseQuery("Item"); + q1.equalTo("inStock", 0); - const q2 = new ParseQuery('Review'); - q2.doesNotMatchKeyInQuery('itemName', 'name', q1); + const q2 = new ParseQuery("Review"); + q2.doesNotMatchKeyInQuery("itemName", "name", q1); expect(q2.toJSON()).toEqual({ where: { itemName: { $dontSelect: { - key: 'name', + key: "name", query: { - className: 'Item', + className: "Item", where: { - inStock: 0 - } - } - } - } - } + inStock: 0, + }, + }, + }, + }, + }, }); }); - it('can generate string-contains queries', () => { - const q = new ParseQuery('Item'); - expect(q.contains.bind(q, 'name', 12)).toThrow( - 'The value being searched for must be a string.' + it("can generate string-contains queries", () => { + const q = new ParseQuery("Item"); + expect(q.contains.bind(q, "name", 12)).toThrow( + "The value being searched for must be a string." ); - q.contains('name', ' or '); + q.contains("name", " or "); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Q or \\E' - } - } + $regex: "\\Q or \\E", + }, + }, }); // Test escaping in quote() - q.contains('name', 'slash-E \\E'); + q.contains("name", "slash-E \\E"); 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'); + q.contains("name", "slash-Q \\Q"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Qslash-Q \\Q\\E' - } - } + $regex: "\\Qslash-Q \\Q\\E", + }, + }, }); }); - it('can generate string-starts-with queries', () => { - const q = new ParseQuery('Item'); - expect(q.startsWith.bind(q, 'name', 12)).toThrow( - 'The value being searched for must be a string.' + it("can generate string-starts-with queries", () => { + const q = new ParseQuery("Item"); + expect(q.startsWith.bind(q, "name", 12)).toThrow( + "The value being searched for must be a string." ); - q.startsWith('name', 'Abc'); + q.startsWith("name", "Abc"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '^\\QAbc\\E' - } - } + $regex: "^\\QAbc\\E", + }, + }, }); - q.startsWith('name', 'Def'); + q.startsWith("name", "Def"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '^\\QDef\\E' - } - } + $regex: "^\\QDef\\E", + }, + }, }); }); - it('can generate string-ends-with queries', () => { - const q = new ParseQuery('Item'); - expect(q.endsWith.bind(q, 'name', 12)).toThrow( - 'The value being searched for must be a string.' + it("can generate string-ends-with queries", () => { + const q = new ParseQuery("Item"); + expect(q.endsWith.bind(q, "name", 12)).toThrow( + "The value being searched for must be a string." ); - q.endsWith('name', 'XYZ'); + q.endsWith("name", "XYZ"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\QXYZ\\E$' - } - } + $regex: "\\QXYZ\\E$", + }, + }, }); - q.endsWith('name', 'xyz'); + q.endsWith("name", "xyz"); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Qxyz\\E$' - } - } + $regex: "\\Qxyz\\E$", + }, + }, }); }); - it('can generate near-geopoint queries', () => { - const q = new ParseQuery('Shipment'); - q.near('shippedTo', new ParseGeoPoint(10, 20)); + it("can generate near-geopoint queries", () => { + const q = new ParseQuery("Shipment"); + q.near("shippedTo", new ParseGeoPoint(10, 20)); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 10, - longitude: 20 - } - } - } + longitude: 20, + }, + }, + }, }); - q.near('shippedTo', [30, 40]); + q.near("shippedTo", [30, 40]); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 30, - longitude: 40 - } - } - } + longitude: 40, + }, + }, + }, }); // GeoPoint's internal fallback - q.near('shippedTo', 'string'); + q.near("shippedTo", "string"); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 0, - longitude: 0 - } - } - } + longitude: 0, + }, + }, + }, }); }); - it('can generate near-geopoint queries with ranges', () => { - const q = new ParseQuery('Shipment'); - q.withinRadians('shippedTo', [20, 40], 2, true); + it("can generate near-geopoint queries with ranges", () => { + const q = new ParseQuery("Shipment"); + q.withinRadians("shippedTo", [20, 40], 2, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 20, - longitude: 40 + longitude: 40, }, - $maxDistance: 2 - } - } + $maxDistance: 2, + }, + }, }); - q.withinMiles('shippedTo', [20, 30], 3958.8, true); + q.withinMiles("shippedTo", [20, 30], 3958.8, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 20, - longitude: 30 + longitude: 30, }, - $maxDistance: 1 - } - } + $maxDistance: 1, + }, + }, }); - q.withinKilometers('shippedTo', [30, 30], 6371.0, true); + q.withinKilometers("shippedTo", [30, 30], 6371.0, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 30, - longitude: 30 + longitude: 30, }, - $maxDistance: 1 - } - } + $maxDistance: 1, + }, + }, }); }); - it('can generate near-geopoint queries without sorting', () => { - const q = new ParseQuery('Shipment'); - q.withinRadians('shippedTo', new ParseGeoPoint(20, 40), 2, false); + it("can generate near-geopoint queries without sorting", () => { + const q = new ParseQuery("Shipment"); + q.withinRadians("shippedTo", new ParseGeoPoint(20, 40), 2, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { $geoWithin: { $centerSphere: [ [40, 20], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 2 - ] - } - } - } + 2, + ], + }, + }, + }, }); - q.withinMiles('shippedTo', new ParseGeoPoint(20, 30), 3958.8, false); + q.withinMiles("shippedTo", new ParseGeoPoint(20, 30), 3958.8, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { $geoWithin: { $centerSphere: [ [30, 20], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 1 - ] - } - } - } + 1, + ], + }, + }, + }, }); - q.withinKilometers('shippedTo', new ParseGeoPoint(30, 30), 6371.0, false); + q.withinKilometers("shippedTo", new ParseGeoPoint(30, 30), 6371.0, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { $geoWithin: { $centerSphere: [ [30, 30], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 1 - ] - } - } - } + 1, + ], + }, + }, + }, }); }); - it('can generate geobox queries', () => { - const q = new ParseQuery('Shipment'); - q.withinGeoBox('shippedTo', [20, 20], [10, 30]); + it("can generate geobox queries", () => { + const q = new ParseQuery("Shipment"); + q.withinGeoBox("shippedTo", [20, 20], [10, 30]); expect(q.toJSON()).toEqual({ 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, + }, + ], + }, + }, + }, }); }); - it('can combine multiple clauses', () => { - const q = new ParseQuery('Item'); - q.lessThan('inStock', 10); - q.greaterThan('inStock', 0); + it("can combine multiple clauses", () => { + const q = new ParseQuery("Item"); + q.lessThan("inStock", 10); + q.greaterThan("inStock", 0); expect(q.toJSON()).toEqual({ where: { inStock: { $lt: 10, - $gt: 0 - } - } + $gt: 0, + }, + }, }); - q.containedIn('size', ['small', 'medium']); + q.containedIn("size", ["small", "medium"]); expect(q.toJSON()).toEqual({ where: { inStock: { $lt: 10, - $gt: 0 + $gt: 0, }, size: { - $in: ['small', 'medium'] - } - } + $in: ["small", "medium"], + }, + }, }); }); - it('can specify ordering', () => { - const q = new ParseQuery('Item'); - q.greaterThan('inStock', 0).ascending('createdAt'); + it("can specify ordering", () => { + const q = new ParseQuery("Item"); + q.greaterThan("inStock", 0).ascending("createdAt"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'createdAt' + order: "createdAt", }); // overrides - q.ascending('name'); + q.ascending("name"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'name' + order: "name", }); - q.ascending('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 - q.addAscending('name'); + q.addAscending("name"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'createdAt,name' + order: "createdAt,name", }); - q.ascending(['a', 'b', 'c']); + 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'); + q.ascending("name", "createdAt"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'name,createdAt' + order: "name,createdAt", }); - q.descending('createdAt'); + q.descending("createdAt"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-createdAt' + order: "-createdAt", }); - q.addAscending('name'); + q.addAscending("name"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-createdAt,name' + order: "-createdAt,name", }); - q.addDescending('a', 'b', 'c'); + 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']); + 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'); + const q2 = new ParseQuery("Item"); q2.addDescending(); expect(q2.toJSON()).toEqual({ where: {}, - order: '', + order: "", }); - const q3 = new ParseQuery('Item'); + const q3 = new ParseQuery("Item"); q3.addAscending(); expect(q3.toJSON()).toEqual({ where: {}, - order: '', + order: "", }); }); - 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' + 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' + "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'); + 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' + 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" ); 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' + 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" ); q.withCount(true); expect(q.toJSON()).toEqual({ where: {}, - count: 1 + count: 1, }); q.withCount(false); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); - it('can set hint value', () => { - const q = new ParseQuery('Item'); - q.hint('_id_'); + it("can set hint value", () => { + const q = new ParseQuery("Item"); + q.hint("_id_"); expect(q.toJSON()).toEqual({ where: {}, - hint: '_id_', + hint: "_id_", }); }); - it('can set explain value', () => { - const q = new ParseQuery('Item'); + it("can set explain value", () => { + const q = new ParseQuery("Item"); q.explain(); const json = q.toJSON(); expect(json).toEqual({ where: {}, explain: true, }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); expect(q2._explain).toBe(true); @@ -1026,148 +1021,148 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: {}, }); - expect(q.explain.bind(q, 'not boolean')).toThrow('You can only set explain to a boolean value'); + expect(q.explain.bind(q, "not boolean")).toThrow( + "You can only set explain to a boolean value" + ); }); - it('can generate queries that include full data for pointers', () => { - const q = new ParseQuery('Item'); - q.greaterThan('inStock', 0); - q.include('manufacturer'); + it("can generate queries that include full data for pointers", () => { + const q = new ParseQuery("Item"); + q.greaterThan("inStock", 0); + q.include("manufacturer"); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - include: 'manufacturer' + include: "manufacturer", }); - q.include('previousModel', 'nextModel'); + 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", }); }); - it('can includeAll for pointers', () => { - const q = new ParseQuery('Item'); + it("can includeAll for pointers", () => { + const q = new ParseQuery("Item"); q.includeAll(); const json = q.toJSON(); expect(json).toEqual({ where: {}, - include: '*', + include: "*", }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); - expect(q2._include).toEqual(['*']); + expect(q2._include).toEqual(["*"]); }); - it('can exclude keys', () => { - const q = new ParseQuery('Item'); - q.exclude('foo'); + it("can exclude keys", () => { + const q = new ParseQuery("Item"); + q.exclude("foo"); const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: 'foo' + excludeKeys: "foo", }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); - expect(q2._exclude).toEqual(['foo']); + expect(q2._exclude).toEqual(["foo"]); }); - it('can exclude multiple keys', () => { - const q = new ParseQuery('Item'); - q.exclude(['foo', 'bar']); + it("can exclude multiple keys", () => { + const q = new ParseQuery("Item"); + q.exclude(["foo", "bar"]); const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: 'foo,bar' + excludeKeys: "foo,bar", }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); - expect(q2._exclude).toEqual(['foo', 'bar']); + expect(q2._exclude).toEqual(["foo", "bar"]); }); - it('can use extraOptions', () => { - const q = new ParseQuery('Item'); - q._extraOptions.randomOption = 'test'; + it("can use extraOptions", () => { + const q = new ParseQuery("Item"); + q._extraOptions.randomOption = "test"; const json = q.toJSON(); expect(json).toEqual({ where: {}, - randomOption: 'test', + randomOption: "test", }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); - expect(q2._extraOptions.randomOption).toBe('test'); + expect(q2._extraOptions.randomOption).toBe("test"); }); - it('can use hint', () => { - const q = new ParseQuery('Item'); - q.hint('_id_'); + it("can use hint", () => { + const q = new ParseQuery("Item"); + q.hint("_id_"); const json = q.toJSON(); expect(json).toEqual({ where: {}, - hint: '_id_', + hint: "_id_", }); - const q2 = new ParseQuery('Item'); + const q2 = new ParseQuery("Item"); q2.withJSON(json); - expect(q2._hint).toBe('_id_'); + expect(q2._hint).toBe("_id_"); }); - it('can specify certain fields to send back', () => { - const q = new ParseQuery('Item'); - q.select('size'); + it("can specify certain fields to send back", () => { + const q = new ParseQuery("Item"); + q.select("size"); expect(q.toJSON()).toEqual({ where: {}, - keys: 'size' + keys: "size", }); - q.select('inStock', 'lastPurchase'); + 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'); + 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.' + "All queries must be for the same class." ); - q2 = new ParseQuery('Item'); - q.equalTo('size', 'medium'); - q2.equalTo('size', 'large'); + q2 = new ParseQuery("Item"); + q.equalTo("size", "medium"); + q2.equalTo("size", "large"); 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,33 +1170,27 @@ 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'); + 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.' + "All queries must be for the same class." ); - q2 = new ParseQuery('Item'); - q.equalTo('size', 'medium'); - q2.equalTo('size', 'large'); + q2 = new ParseQuery("Item"); + q.equalTo("size", "medium"); + q2.equalTo("size", "large"); 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,32 +1198,26 @@ 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'); + 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.', + "All queries must be for the same class." ); - q2 = new ParseQuery('Item'); - q.equalTo('size', 'medium'); - q2.equalTo('size', 'large'); + q2 = new ParseQuery("Item"); + q.equalTo("size", "medium"); + q2.equalTo("size", "large"); let mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [ - { size: 'medium' }, - { size: 'large' }, - ], + $nor: [{ size: "medium" }, { size: "large" }], }, }); @@ -1243,344 +1226,347 @@ 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); 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' + 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", + }); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 1, where: { - size: 'small' - } + size: "small", + }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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(); - }); + const q = new ParseQuery("Item"); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); 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' + objectId: "I1", + size: "small", + name: "Product 3", }, }); - } + }, }); - const q = new ParseQuery('Item'); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); 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) => { + const q = new ParseQuery("Item"); + q.get("I27").then((obj) => { expect(obj instanceof ParseObject).toBe(true); - expect(obj.className).toBe('Item'); - expect(obj.id).toBe('I27'); + expect(obj.className).toBe("Item"); + expect(obj.id).toBe("I27"); expect(obj.attributes).toEqual({ - size: 'large', - name: 'Product 27' + size: "large", + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); 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(); - }); + 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(); + } + ); }); - 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 1, where: { - objectId: 'I27' - } + objectId: "I27", + }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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', { + const q = new ParseQuery("Item"); + q.get("I27", { useMasterKey: true, - sessionToken: '1234', - context: context + sessionToken: "1234", + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ 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(); - }); + const q = new ParseQuery("Item"); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 0, count: 1, where: { - size: 'small' - } + size: "small", + }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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(); - }); + const q = new ParseQuery("Item"); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 2, skip: 8, - keys: 'size,name', - order: 'createdAt', + keys: "size,name", + order: "createdAt", where: { size: { - $in: ['small', 'medium'] - } + $in: ["small", "medium"], + }, }, - readPreference: 'PRIMARY', - includeReadPreference: 'SECONDARY', - subqueryReadPreference: 'SECONDARY_PREFERRED', + readPreference: "PRIMARY", + includeReadPreference: "SECONDARY", + subqueryReadPreference: "SECONDARY_PREFERRED", }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - ] + { objectId: "I55", size: "medium", name: "Product 55" }, + { objectId: "I89", size: "small", name: "Product 89" }, + ], }); - } + }, }); - const q = new ParseQuery('Item'); - q.containedIn('size', ['small', 'medium']) + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]) .limit(2) .skip(8) - .ascending('createdAt') - .select('size', 'name') - .readPreference('PRIMARY', 'SECONDARY', 'SECONDARY_PREFERRED') + .ascending("createdAt") + .select("size", "name") + .readPreference("PRIMARY", "SECONDARY", "SECONDARY_PREFERRED") .find() .then((objs) => { expect(objs.length).toBe(2); expect(objs[0] instanceof ParseObject).toBe(true); expect(objs[0].attributes).toEqual({ - size: 'medium', - name: 'Product 55' + size: "medium", + name: "Product 55", }); expect(objs[1] instanceof ParseObject).toBe(true); expect(objs[1].attributes).toEqual({ - size: 'small', - name: 'Product 89' + size: "small", + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ where: { size: { - $in: ['small', 'medium'] - } - } + $in: ["small", "medium"], + }, + }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); expect(options.context).toEqual(context); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); - const q = new ParseQuery('Item'); - q.containedIn('size', ['small', 'medium']) + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]) .find({ useMasterKey: true, - sessionToken: '1234', - context: context + sessionToken: "1234", + context: context, }) .then((objs) => { expect(objs).toEqual([]); @@ -1588,324 +1574,332 @@ describe('ParseQuery', () => { }); }); - 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(className).toBe("Item"); expect(params).toEqual({ where: {}, - count: 1 + count: 1, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); return Promise.resolve({ - results:[ - { objectId: '1', name: 'Product 55' }, - { objectId: '2', name: 'Product 89' } ], - count: 2 + results: [ + { objectId: "1", name: "Product 55" }, + { objectId: "2", name: "Product 89" }, + ], + count: 2, }); - } + }, }); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); q.withCount(true) .find({ useMasterKey: true, - sessionToken: '1234' + sessionToken: "1234", }) .then((obj) => { expect(obj.results).toBeDefined(); expect(obj.results.length).toBe(2); expect(obj.count).toBeDefined(); - expect(typeof obj.count).toBe('number'); + expect(typeof obj.count).toBe("number"); done(); }); }); - describe('iterating over batches with .eachBatch()', () => { + describe("iterating over batches with .eachBatch()", () => { 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, }); }); - it('passes query attributes through to the REST API', async () => { - const q = new ParseQuery('Item'); - q.containedIn('size', ['small', 'medium']); + 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) + "name", + "productName", + new ParseQuery("Review").equalTo("stars", 5) ); - q.equalTo('valid', true); - q.equalTo('arrayField', ['a', 'b']); - q.select('size', 'name'); + q.equalTo("valid", true); + q.equalTo("arrayField", ["a", "b"]); + q.select("size", "name"); q.includeAll(); - q.hint('_id_'); + q.hint("_id_"); await q.eachBatch(() => {}); 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', - keys: 'size,name', - include: '*', - hint: '_id_', + order: "objectId", + keys: "size,name", + include: "*", + hint: "_id_", where: { - arrayField: ['a', 'b'], + arrayField: ["a", "b"], size: { - $in: ['small', 'medium'] + $in: ["small", "medium"], }, name: { $select: { - key: 'productName', + key: "productName", query: { - className: 'Review', + className: "Review", where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); }); - it('passes options through to the REST API', async () => { + it("passes options through to the REST API", async () => { const batchOptions = { useMasterKey: true, - sessionToken: '1234', + sessionToken: "1234", batchSize: 50, }; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.eachBatch(() => {}, batchOptions); expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 50, - order: 'objectId', + order: "objectId", where: {}, }); expect(options.useMasterKey).toBe(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); }); - it('only makes one request when the results fit in one page', async () => { - const q = new ParseQuery('Item'); + it("only makes one request when the results fit in one page", async () => { + const q = new ParseQuery("Item"); await q.eachBatch(() => {}); expect(findMock).toHaveBeenCalledTimes(1); }); - it('makes more requests when the results do not fit in one page', async () => { - const q = new ParseQuery('Item'); + it("makes more requests when the results do not fit in one page", async () => { + 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 () => { + it("stops iteration when the callback returns a promise that rejects", async () => { let callCount = 0; const callback = () => { callCount++; - return Promise.reject(new Error('Callback rejecting')); + return Promise.reject(new Error("Callback rejecting")); }; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.eachBatch(callback, { batchSize: 2 }).catch(() => {}); expect(callCount).toBe(1); }); - it('handles a synchronous callback', async () => { + it("handles a synchronous callback", async () => { const results = []; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.eachBatch((items) => { - items.map(item => results.push(item.attributes.size)) + items.map((item) => results.push(item.attributes.size)); }); - expect(results).toEqual(['medium', 'small']); + expect(results).toEqual(["medium", "small"]); }); - it('handles an asynchronous callback', async () => { + it("handles an asynchronous callback", async () => { const results = []; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.eachBatch((items) => { - items.map(item => results.push(item.attributes.size)) - return new Promise(resolve => setImmediate(resolve)); + items.map((item) => results.push(item.attributes.size)); + return new Promise((resolve) => setImmediate(resolve)); }); - expect(results).toEqual(['medium', 'small']); + expect(results).toEqual(["medium", "small"]); }); }); - describe('return all objects with .findAll()', () => { + describe("return all objects with .findAll()", () => { 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, }); }); - it('passes query attributes through to the REST API', async () => { - const q = new ParseQuery('Item'); - q.containedIn('size', ['small', 'medium']); + 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) + "name", + "productName", + new ParseQuery("Review").equalTo("stars", 5) ); - q.equalTo('valid', true); - q.select('size', 'name'); + q.equalTo("valid", true); + q.select("size", "name"); q.includeAll(); - q.hint('_id_'); + q.hint("_id_"); 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', - keys: 'size,name', - include: '*', - hint: '_id_', + order: "objectId", + keys: "size,name", + include: "*", + hint: "_id_", where: { size: { - $in: ['small', 'medium'] + $in: ["small", "medium"], }, name: { $select: { - key: 'productName', + key: "productName", query: { - className: 'Review', + className: "Review", where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); }); - it('passes options through to the REST API', async () => { + it("passes options through to the REST API", async () => { const batchOptions = { useMasterKey: true, - sessionToken: '1234', + sessionToken: "1234", batchSize: 50, }; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.findAll(batchOptions); expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 50, - order: 'objectId', + order: "objectId", where: {}, }); expect(options.useMasterKey).toBe(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); }); - it('only makes one request when the results fit in one page', async () => { - const q = new ParseQuery('Item'); + it("only makes one request when the results fit in one page", async () => { + const q = new ParseQuery("Item"); await q.findAll(); expect(findMock).toHaveBeenCalledTimes(1); }); - it('makes more requests when the results do not fit in one page', async () => { - const q = new ParseQuery('Item'); + it("makes more requests when the results do not fit in one page", async () => { + const q = new ParseQuery("Item"); await q.findAll({ batchSize: 2 }); expect(findMock).toHaveBeenCalledTimes(2); - }) + }); - it('Returns all objects', async () => { - const q = new ParseQuery('Item'); + it("Returns all objects", async () => { + const q = new ParseQuery("Item"); const results = await q.findAll(); - expect(results.map(obj => obj.attributes.size)).toEqual(['medium', 'small']); + expect(results.map((obj) => obj.attributes.size)).toEqual([ + "medium", + "small", + ]); }); }); - it('can iterate over results with each()', (done) => { + it("can iterate over results with each()", (done) => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 100, - order: 'objectId', - keys: 'size,name', - include: '*', + order: "objectId", + keys: "size,name", + include: "*", where: { size: { - $in: ['small', 'medium'] + $in: ["small", "medium"], }, name: { $select: { - key: 'productName', + key: "productName", query: { - className: 'Review', + className: "Review", where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + { 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']); + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]); q.matchesKeyInQuery( - 'name', - 'productName', - new ParseQuery('Review').equalTo('stars', 5) + "name", + "productName", + new ParseQuery("Review").equalTo("stars", 5) ); - q.equalTo('valid', true); - q.select('size', 'name'); + q.equalTo("valid", true); + q.select("size", "name"); q.includeAll(); let calls = 0; @@ -1917,895 +1911,934 @@ 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 100, - order: 'objectId', - keys: 'size,name', + order: "objectId", + 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'); + expect(options.sessionToken).toEqual("1234"); expect(options.context).toEqual(context); return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + { 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.equalTo('valid', true); - q.select('size', 'name'); + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]); + q.equalTo("valid", true); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ limit: 100, - order: 'objectId', - keys: 'size,name', + order: "objectId", + keys: "size,name", where: { size: { - $in: ['small', 'medium'] + $in: ["small", "medium"], }, - valid: true + valid: true, }, - hint: '_id_', + hint: "_id_", }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); expect(options.context).toEqual(context); return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + { 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.equalTo('valid', true); - q.select('size', 'name'); - q.hint('_id_'); + const q = new ParseQuery("Item"); + q.containedIn("size", ["small", "medium"]); + q.equalTo("valid", true); + q.select("size", "name"); + 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(); }); }); - it('should add hint as string', () => { - const q = new ParseQuery('Item'); - q.hint('_id_'); - expect(q._hint).toBe('_id_'); + it("should add hint as string", () => { + const q = new ParseQuery("Item"); + q.hint("_id_"); + expect(q._hint).toBe("_id_"); }); - it('should set hint as object', () => { - const q = new ParseQuery('Item'); + it("should set hint as object", () => { + const q = new ParseQuery("Item"); q.hint({ _id: 1 }); expect(q._hint).toStrictEqual({ _id: 1 }); }); - it('should delete hint when set as undefined', () => { - const q = new ParseQuery('Item'); - q.hint('_id_'); - expect(q._hint).toBe('_id_'); + it("should delete hint when set as undefined", () => { + const q = new ParseQuery("Item"); + q.hint("_id_"); + expect(q._hint).toBe("_id_"); q.hint(); expect(q._hint).toBeUndefined(); }); - describe('iterating over results via .map()', () => { + describe("iterating over results via .map()", () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + { 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 () => { + it("can iterate with a synchronous callback", async () => { const callback = (object) => object.attributes.size; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); const results = await q.map(callback); - expect(results).toEqual(['medium', 'small', 'small']); + expect(results).toEqual(["medium", "small", "small"]); }); - it('can iterate with an asynchronous callback', async () => { + it("can iterate with an asynchronous callback", async () => { const callback = async (object) => object.attributes.size; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); const results = await q.map(callback); - expect(results).toEqual(['medium', 'small', 'small']); + expect(results).toEqual(["medium", "small", "small"]); }); - it('stops iteration when a rejected promise is returned', async () => { + 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); }); }); - describe('iterating over results with .reduce()', () => { + describe("iterating over results with .reduce()", () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: 'I55', number: 1 }, - { objectId: 'I89', number: 2 }, - { objectId: 'I91', number: 3 }, - ] + { objectId: "I55", number: 1 }, + { objectId: "I89", number: 2 }, + { objectId: "I91", number: 3 }, + ], }); - } + }, }); }); - it('can iterate with a synchronous callback', async () => { - const callback = (accumulator, object) => accumulator + object.attributes.number; - const q = new ParseQuery('Item'); + it("can iterate with a synchronous callback", async () => { + const callback = (accumulator, object) => + accumulator + object.attributes.number; + const q = new ParseQuery("Item"); const result = await q.reduce(callback, 0); expect(result).toBe(6); }); - it('can iterate with an asynchronous callback', async () => { - const callback = async (accumulator, object) => accumulator + object.attributes.number; - const q = new ParseQuery('Item'); + it("can iterate with an asynchronous callback", async () => { + const callback = async (accumulator, object) => + accumulator + object.attributes.number; + const q = new ParseQuery("Item"); const result = await q.reduce(callback, 0); expect(result).toBe(6); }); - it('stops iteration when a rejected promise is returned', async () => { + it("stops iteration when a rejected promise is returned", async () => { let callCount = 0; const callback = () => { callCount += 1; return Promise.reject(new Error("Callback rejecting")); - } - const q = new ParseQuery('Item'); + }; + const q = new ParseQuery("Item"); await q.reduce(callback, 0).catch(() => {}); expect(callCount).toBe(1); }); - it('uses the first object as an initial value when no initial value is passed', async () => { + it("uses the first object as an initial value when no initial value is passed", async () => { let callCount = 0; const callback = (accumulator, object) => { callCount += 1; accumulator.attributes.number += object.attributes.number; return accumulator; - } - const q = new ParseQuery('Item'); + }; + const q = new ParseQuery("Item"); const result = await q.reduce(callback); - expect(result.id).toBe('I55'); + expect(result.id).toBe("I55"); expect(result.attributes.number).toBe(6); expect(callCount).toBe(2); // Not called for the first object when used as initial value }); - it('rejects with a TypeError when there are no results and no initial value was provided', async () => { + 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 q = new ParseQuery("Item"); const callback = (accumulator, object) => { accumulator.attributes.number += object.attributes.number; return accumulator; - } + }; return expect(q.reduce(callback)).rejects.toThrow(TypeError); }); }); - describe('iterating over results with .filter()', () => { + describe("iterating over results with .filter()", () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + { 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 q = new ParseQuery('Item'); + it("can iterate results with a synchronous callback", async () => { + 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 q = new ParseQuery('Item'); + it("can iterate results with an async callback", async () => { + const callback = async (object) => object.attributes.size === "small"; + const q = new ParseQuery("Item"); const results = await q.filter(callback); expect(results.length).toBe(2); }); - it('stops iteration when a rejected promise is returned', async () => { + it("stops iteration when a rejected promise is returned", async () => { let callCount = 0; const callback = async () => { callCount += 1; - return Promise.reject(new Error('Callback rejecting')); + return Promise.reject(new Error("Callback rejecting")); }; - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); await q.filter(callback).catch(() => {}); expect(callCount).toBe(1); }); }); - it('returns an error when iterating over an invalid query', (done) => { - const q = new ParseQuery('Item'); + 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', () => { - CoreManager.set('PERFORM_USER_REWRITE', true); - let q = new ParseQuery('User'); - expect(q.className).toBe('_User'); - CoreManager.set('PERFORM_USER_REWRITE', false); - q = new ParseQuery('User'); - expect(q.className).toBe('User'); + it("rewrites User queries when the rewrite is enabled", () => { + CoreManager.set("PERFORM_USER_REWRITE", true); + let q = new ParseQuery("User"); + expect(q.className).toBe("_User"); + CoreManager.set("PERFORM_USER_REWRITE", false); + q = new ParseQuery("User"); + 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' }, - ] + { className: "Product", objectId: "P40", name: "Product 40" }, + ], }); - } + }, }); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); q.find().then((results) => { - expect(results[0].className).toBe('Product'); + 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'); + const q = new ParseQuery("Item"); q.find().then((results) => { - expect(results[0].className).toBe('Product'); + expect(results[0].className).toBe("Product"); done(); }); }); - - it('overrides cached object with query results', (done) => { + it("overrides cached object with query results", (done) => { jest.dontMock("../ParseObject"); jest.resetModules(); - ParseObject = require('../ParseObject').default; - CoreManager = require('../CoreManager'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: 'T01', - name: 'Name', - other: 'other', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + objectId: "T01", + name: "Name", + other: "other", + className: "Thing", + createdAt: "2017-01-10T10:00:00Z", }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); const q = new ParseQuery("Thing"); let testObject; - q.find().then((results) => { - testObject = results[0]; + q.find() + .then((results) => { + testObject = results[0]; - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); + 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(); - }); + 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) => { + it("does not override unselected fields with select query results", (done) => { jest.dontMock("../ParseObject"); jest.resetModules(); - ParseObject = require('../ParseObject').default; - CoreManager = require('../CoreManager'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: 'T01', - name: 'Name', - other: 'other', - tbd: 'exists', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z', - subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"} + objectId: "T01", + name: "Name", + other: "other", + tbd: "exists", + className: "Thing", + createdAt: "2017-01-10T10:00:00Z", + subObject: { key1: "value", key2: "value2", key3: "thisWillGoAway" }, }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); 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) => { + it("overrides cached object with first() results", (done) => { jest.dontMock("../ParseObject"); jest.resetModules(); - ParseObject = require('../ParseObject').default; - CoreManager = require('../CoreManager'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: 'T01', - name: 'Name', - other: 'other', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + objectId: "T01", + name: "Name", + other: "other", + className: "Thing", + createdAt: "2017-01-10T10:00:00Z", }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); 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) => { + it("does not override unselected fields for first() on select query", (done) => { jest.dontMock("../ParseObject"); jest.resetModules(); - ParseObject = require('../ParseObject').default; - CoreManager = require('../CoreManager'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: 'T01', - name: 'Name', - other: 'other', - tbd: 'exists', - className:"Thing", - subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"}, - createdAt: '2017-01-10T10:00:00Z', + objectId: "T01", + name: "Name", + other: "other", + tbd: "exists", + className: "Thing", + subObject: { key1: "value", key2: "value2", key3: "thisWillGoAway" }, + createdAt: "2017-01-10T10:00:00Z", }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); 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', () => { - const q = new ParseQuery('Item'); + it("restores queries from json representation", () => { + const q = new ParseQuery("Item"); - q.include('manufacturer'); - q.select('inStock', 'lastPurchase'); + q.include("manufacturer"); + q.select("inStock", "lastPurchase"); q.limit(10); q.withCount(true); - q.ascending(['a', 'b', 'c']); + q.ascending(["a", "b", "c"]); q.skip(4); - q.equalTo('size', 'medium'); + q.equalTo("size", "medium"); const json = q.toJSON(); - const newQuery = ParseQuery.fromJSON('Item', json); + const newQuery = ParseQuery.fromJSON("Item", json); - expect(newQuery.className).toBe('Item'); + expect(newQuery.className).toBe("Item"); expect(newQuery.toJSON()).toEqual({ - include: 'manufacturer', - keys: 'inStock,lastPurchase', + include: "manufacturer", + keys: "inStock,lastPurchase", limit: 10, count: 1, - order: 'a,b,c', + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ - distinct: 'size', + distinct: "size", where: { - size: 'small' - } + size: "small", + }, }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: ['L'], + results: ["L"], }); - } + }, }); - const q = new ParseQuery('Item'); - q.equalTo('size', 'small').distinct('size').then((results) => { - expect(results[0]).toBe('L'); - done(); - }); + const q = new ParseQuery("Item"); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ - distinct: 'size', + distinct: "size", where: { - size: 'small' - } + size: "small", + }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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(); - }); + const q = new ParseQuery("Item"); + 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) { - expect(className).toBe('Item'); + expect(className).toBe("Item"); expect(params).toEqual({ - distinct: 'size', + distinct: "size", where: { - size: 'small' + size: "small", }, - hint: '_id_', + hint: "_id_", }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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(); - }); + const q = new ParseQuery("Item"); + 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', () => { - const q = new ParseQuery('Item'); - q.readPreference('PRIMARY', 'SECONDARY', 'SECONDARY_PREFERRED'); + it("can issue a query to the controller", () => { + const q = new ParseQuery("Item"); + q.readPreference("PRIMARY", "SECONDARY", "SECONDARY_PREFERRED"); const json = q.toJSON(); expect(json).toEqual({ where: {}, - readPreference: 'PRIMARY', - includeReadPreference: 'SECONDARY', - subqueryReadPreference: 'SECONDARY_PREFERRED', + readPreference: "PRIMARY", + includeReadPreference: "SECONDARY", + subqueryReadPreference: "SECONDARY_PREFERRED", }); - const query = ParseQuery.fromJSON('Item', json); - expect(query._readPreference).toBe('PRIMARY'); - expect(query._includeReadPreference).toBe('SECONDARY'); - expect(query._subqueryReadPreference).toBe('SECONDARY_PREFERRED'); + const query = ParseQuery.fromJSON("Item", json); + expect(query._readPreference).toBe("PRIMARY"); + expect(query._includeReadPreference).toBe("SECONDARY"); + 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) { - expect(className).toBe('Item'); - expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); + expect(className).toBe("Item"); + expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [], }); - } + }, }); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); 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: [], }); }); - const q = new ParseQuery('Item'); - q.equalTo('name', 'foo'); + const q = new ParseQuery("Item"); + q.equalTo("name", "foo"); 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({ results: [], }); }); - const q = new ParseQuery('Item'); - q.equalTo('name', 'foo'); + const q = new ParseQuery("Item"); + q.equalTo("name", "foo"); 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() {}, aggregate(className, params, options) { - expect(className).toBe('Item'); - expect(params.pipeline).toEqual({ group: { objectId: '$name' } }); + expect(className).toBe("Item"); + expect(params.pipeline).toEqual({ group: { objectId: "$name" } }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [], }); - } + }, }); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); 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(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 { - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); q.aggregate(pipeline).then(() => {}); } catch (e) { done(); } }); - 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) { - expect(className).toBe('Item'); - expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); + expect(className).toBe("Item"); + expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + expect(options.sessionToken).toEqual("1234"); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); q.aggregate(pipeline, { - sessionToken: '1234' + 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() {}, aggregate(className, params, options) { - expect(className).toBe('Item'); - expect(params.readPreference).toEqual('SECONDARY'); + expect(className).toBe("Item"); + expect(params.readPreference).toEqual("SECONDARY"); expect(options.useMasterKey).toEqual(true); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); // Query - const q = new ParseQuery('Item'); - q.readPreference('SECONDARY'); - const results = await q.aggregate([], { sessionToken: '1234' }); + const q = new ParseQuery("Item"); + q.readPreference("SECONDARY"); + const results = await q.aggregate([], { sessionToken: "1234" }); // Validate 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) { - expect(className).toBe('Item'); - expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); - expect(params.hint).toEqual('_id_'); + expect(className).toBe("Item"); + expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); + expect(params.hint).toEqual("_id_"); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual('1234'); + 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(); - }); + const q = new ParseQuery("Item"); + q.hint("_id_") + .aggregate(pipeline, { + sessionToken: "1234", + }) + .then((results) => { + expect(results).toEqual([]); + done(); + }); }); - it('can cancel query', async () => { + it("can cancel query", async () => { const mockRequestTask = { abort: () => {}, }; CoreManager.setQueryController({ - find: function(name, params, options) { + find: function (name, params, options) { options.requestTask(mockRequestTask); return Promise.resolve({ - results: [] + results: [], }); }, aggregate: () => {}, }); - const query = new ParseQuery('TestCancel'); + const query = new ParseQuery("TestCancel"); expect(query._xhrRequest).toBeDefined(); expect(query._xhrRequest.task).toBe(null); expect(query._xhrRequest.onchange()).toBeUndefined(); - jest.spyOn(mockRequestTask, 'abort'); + jest.spyOn(mockRequestTask, "abort"); query.cancel(); expect(mockRequestTask.abort).toHaveBeenCalledTimes(0); @@ -2816,130 +2849,153 @@ describe('ParseQuery', () => { expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); }); - it('selecting sub-objects does not inject objects when sub-object does not exist', (done) => { + 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'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); const objectToReturn = { - objectId: 'T01', - name: 'Name', - tbd: 'exists', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + objectId: "T01", + name: "Name", + tbd: "exists", + 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") + 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) => { + 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'); - ParseQuery = require('../ParseQuery').default; + ParseObject = require("../ParseObject").default; + CoreManager = require("../CoreManager"); + ParseQuery = require("../ParseQuery").default; ParseObject.enableSingleInstance(); let objectToReturn = { - 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' + 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", }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); 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', () => { - const query = new ParseQuery('Item'); - query.fullText('size', 'small'); + it("full text search", () => { + const query = new ParseQuery("Item"); + query.fullText("size", "small"); expect(query.toJSON()).toEqual({ where: { size: { $text: { $search: { - $term: "small" - } - } - } - } + $term: "small", + }, + }, + }, + }, }); }); - it('full text search sort', () => { - const query = new ParseQuery('Item'); - query.fullText('size', 'medium'); - query.ascending('$score'); - query.select('$score'); + it("full text search sort", () => { + const query = new ParseQuery("Item"); + query.fullText("size", "medium"); + query.ascending("$score"); + query.select("$score"); expect(query.toJSON()).toEqual({ where: { @@ -2947,51 +3003,59 @@ describe('ParseQuery', () => { $text: { $search: { $term: "medium", - } - } - } + }, + }, + }, }, - keys : "$score", - order : "$score" + keys: "$score", + order: "$score", }); }); - it('full text search key required', (done) => { - const query = new ParseQuery('Item'); - expect(() => query.fullText()).toThrow('A key is required.'); + 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) => { - const query = new ParseQuery('Item'); - expect(() => query.fullText('key')).toThrow('A search term is required'); + 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) => { - const query = new ParseQuery('Item'); - expect(() => query.fullText('key', [])).toThrow('The value being searched for must be a string.'); + 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." + ); done(); }); - it('full text search invalid option', (done) => { - const query = new ParseQuery('Item'); - expect(() => query.fullText('size', 'medium', { unknown: 'throwOption' })).toThrow('Unknown option: unknown'); + it("full text search invalid option", (done) => { + const query = new ParseQuery("Item"); + expect(() => + query.fullText("size", "medium", { unknown: "throwOption" }) + ).toThrow("Unknown option: unknown"); done(); }); - it('full text search with all parameters', () => { - const query = new ParseQuery('Item'); + 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: { size: { $text: { $search: { - $term: 'medium', - $language: 'en', + $term: "medium", + $language: "en", $caseSensitive: false, $diacriticSensitive: true, }, @@ -3001,10 +3065,10 @@ describe('ParseQuery', () => { }); }); - it('add the score for the full text search', () => { - const query = new ParseQuery('Item'); + it("add the score for the full text search", () => { + const query = new ParseQuery("Item"); - query.fullText('size', 'medium', { language: 'fr' }); + query.fullText("size", "medium", { language: "fr" }); query.sortByTextScore(); expect(query.toJSON()).toEqual({ @@ -3012,31 +3076,28 @@ describe('ParseQuery', () => { size: { $text: { $search: { - $term: 'medium', - $language: 'fr', + $term: "medium", + $language: "fr", }, }, }, }, - keys: '$score', - order: '$score', + keys: "$score", + order: "$score", }); }); - }); -describe('ParseQuery LocalDatastore', () => { +describe("ParseQuery LocalDatastore", () => { beforeEach(() => { CoreManager.setLocalDatastore(mockLocalDatastore); jest.clearAllMocks(); }); - it('can query from local datastore', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + it("can query from local datastore", () => { + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromLocalDatastore(); @@ -3044,12 +3105,10 @@ describe('ParseQuery LocalDatastore', () => { expect(q._localDatastorePinName).toBe(null); }); - it('can query from default pin', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + it("can query from default pin", () => { + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromPin(); @@ -3061,21 +3120,19 @@ describe('ParseQuery LocalDatastore', () => { expect(query).toEqual(q); }); - it('can query from pin with name', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + it("can query from pin with name", () => { + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery('Item'); + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); - q.fromPinWithName('test_pin'); + q.fromPinWithName("test_pin"); expect(q._queriesLocalDatastore).toBe(true); - expect(q._localDatastorePinName).toBe('test_pin'); + expect(q._localDatastorePinName).toBe("test_pin"); }); - it('cannot query from local datastore if disabled', () => { - const q = new ParseQuery('Item'); + it("cannot query from local datastore if disabled", () => { + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromLocalDatastore(); @@ -3083,8 +3140,8 @@ describe('ParseQuery LocalDatastore', () => { expect(q._localDatastorePinName).toBe(null); }); - it('can query from default pin if disabled', () => { - const q = new ParseQuery('Item'); + it("can query from default pin if disabled", () => { + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromPin(); @@ -3092,428 +3149,418 @@ describe('ParseQuery LocalDatastore', () => { expect(q._localDatastorePinName).toBe(null); }); - it('can query from pin with name if disabled', () => { - const q = new ParseQuery('Item'); + it("can query from pin with name if disabled", () => { + const q = new ParseQuery("Item"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); - q.fromPinWithName('test_pin'); + q.fromPinWithName("test_pin"); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); }); - it('can query offline', async () => { + it("can query offline", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", count: 2, }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", }; const obj3 = { - className: 'Unknown', - objectId: 'objectId3', + className: "Unknown", + 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); + const q = new ParseQuery("Item"); + q.equalTo("count", 2); q.fromLocalDatastore(); const results = await q.find(); expect(results[0].id).toEqual(obj1.objectId); }); - it('can query offline with localId', async () => { + it("can query offline with localId", async () => { const obj1 = { - className: 'Item', - _localId: 'local0', + className: "Item", + _localId: "local0", count: 2, }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", }; const obj3 = { - className: 'Unknown', - objectId: 'objectId3', + className: "Unknown", + 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); + const q = new ParseQuery("Item"); + q.equalTo("count", 2); q.fromLocalDatastore(); const results = await q.find(); expect(results[0]._localId).toEqual(obj1._localId); }); - it('can query offline first', async () => { + it("can query offline first", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", count: 2, }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", }; const obj3 = { - className: 'Unknown', - objectId: 'objectId3', + className: "Unknown", + 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'); + let q = new ParseQuery("Item"); q.fromLocalDatastore(); let result = await q.first(); 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 = new ParseQuery("Item"); q.fromLocalDatastore(); result = await q.first(); expect(result).toEqual(undefined); }); - it('can query offline sort', async () => { + it("can query offline sort", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", password: 123, number: 2, - createdAt: new Date('2018-08-10T00:00:00.000Z'), - updatedAt: new Date('2018-08-10T00:00:00.000Z'), + createdAt: new Date("2018-08-10T00:00:00.000Z"), + updatedAt: new Date("2018-08-10T00:00:00.000Z"), }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", password: 123, number: 3, - createdAt: new Date('2018-08-11T00:00:00.000Z'), - updatedAt: new Date('2018-08-11T00:00:00.000Z'), + createdAt: new Date("2018-08-11T00:00:00.000Z"), + updatedAt: new Date("2018-08-11T00:00:00.000Z"), }; const obj3 = { - className: 'Item', - objectId: 'objectId3', + className: "Item", + objectId: "objectId3", password: 123, number: 4, - createdAt: new Date('2018-08-12T00:00:00.000Z'), - updatedAt: new Date('2018-08-12T00:00:00.000Z'), + createdAt: new Date("2018-08-12T00:00:00.000Z"), + 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'); + let q = new ParseQuery("Item"); + q.ascending("number"); q.fromLocalDatastore(); let results = await q.find(); - expect(results[0].get('number')).toEqual(2); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(4); + expect(results[0].get("number")).toEqual(2); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(4); - q = new ParseQuery('Item'); - q.descending('number'); + q = new ParseQuery("Item"); + q.descending("number"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(4); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); + expect(results[0].get("number")).toEqual(4); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(2); - q = new ParseQuery('Item'); - q.descending('number'); + q = new ParseQuery("Item"); + q.descending("number"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(4); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); + expect(results[0].get("number")).toEqual(4); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(2); - q = new ParseQuery('Item'); - q.descending('_created_at'); + q = new ParseQuery("Item"); + q.descending("_created_at"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(2); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(4); + expect(results[0].get("number")).toEqual(2); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(4); - q = new ParseQuery('Item'); - q.descending('_updated_at'); + q = new ParseQuery("Item"); + q.descending("_updated_at"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(2); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(4); + expect(results[0].get("number")).toEqual(2); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(4); - q = new ParseQuery('Item'); - q.descending('password'); + q = new ParseQuery("Item"); + q.descending("password"); q.fromLocalDatastore(); try { results = await q.find(); } catch (e) { - expect(e.message).toEqual('Invalid Key: password'); + expect(e.message).toEqual("Invalid Key: password"); } }); - it('can query offline sort multiple', async () => { + it("can query offline sort multiple", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", password: 123, number: 3, - string: 'a', + string: "a", }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", number: 1, - string: 'b', + string: "b", }; const obj3 = { - className: 'Item', - objectId: 'objectId3', + className: "Item", + objectId: "objectId3", number: 3, - string: 'c', + string: "c", }; const obj4 = { - className: 'Item', - objectId: 'objectId4', + className: "Item", + objectId: "objectId4", number: 2, - string: 'd', + 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'); + let q = new ParseQuery("Item"); + q.ascending("number,string"); q.fromLocalDatastore(); let results = await q.find(); - expect(results[0].get('number')).toEqual(1); - expect(results[1].get('number')).toEqual(2); - expect(results[2].get('number')).toEqual(3); - expect(results[3].get('number')).toEqual(3); - expect(results[0].get('string')).toEqual('b'); - expect(results[1].get('string')).toEqual('d'); - expect(results[2].get('string')).toEqual('a'); - expect(results[3].get('string')).toEqual('c'); - - q = new ParseQuery('Item'); - q.ascending('number').addDescending('string'); + expect(results[0].get("number")).toEqual(1); + expect(results[1].get("number")).toEqual(2); + expect(results[2].get("number")).toEqual(3); + expect(results[3].get("number")).toEqual(3); + expect(results[0].get("string")).toEqual("b"); + expect(results[1].get("string")).toEqual("d"); + expect(results[2].get("string")).toEqual("a"); + expect(results[3].get("string")).toEqual("c"); + + q = new ParseQuery("Item"); + q.ascending("number").addDescending("string"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(1); - expect(results[1].get('number')).toEqual(2); - expect(results[2].get('number')).toEqual(3); - expect(results[3].get('number')).toEqual(3); - expect(results[0].get('string')).toEqual('b'); - expect(results[1].get('string')).toEqual('d'); - expect(results[2].get('string')).toEqual('c'); - expect(results[3].get('string')).toEqual('a'); - - q = new ParseQuery('Item'); - q.descending('number,string'); + expect(results[0].get("number")).toEqual(1); + expect(results[1].get("number")).toEqual(2); + expect(results[2].get("number")).toEqual(3); + expect(results[3].get("number")).toEqual(3); + expect(results[0].get("string")).toEqual("b"); + expect(results[1].get("string")).toEqual("d"); + expect(results[2].get("string")).toEqual("c"); + expect(results[3].get("string")).toEqual("a"); + + q = new ParseQuery("Item"); + q.descending("number,string"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(3); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); - expect(results[3].get('number')).toEqual(1); - expect(results[0].get('string')).toEqual('c'); - expect(results[1].get('string')).toEqual('a'); - expect(results[2].get('string')).toEqual('d'); - expect(results[3].get('string')).toEqual('b'); - - q = new ParseQuery('Item'); - q.descending('number').addAscending('string'); + expect(results[0].get("number")).toEqual(3); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(2); + expect(results[3].get("number")).toEqual(1); + expect(results[0].get("string")).toEqual("c"); + expect(results[1].get("string")).toEqual("a"); + expect(results[2].get("string")).toEqual("d"); + expect(results[3].get("string")).toEqual("b"); + + q = new ParseQuery("Item"); + q.descending("number").addAscending("string"); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get('number')).toEqual(3); - expect(results[1].get('number')).toEqual(3); - expect(results[2].get('number')).toEqual(2); - expect(results[3].get('number')).toEqual(1); - expect(results[0].get('string')).toEqual('a'); - expect(results[1].get('string')).toEqual('c'); - expect(results[2].get('string')).toEqual('d'); - expect(results[3].get('string')).toEqual('b'); + expect(results[0].get("number")).toEqual(3); + expect(results[1].get("number")).toEqual(3); + expect(results[2].get("number")).toEqual(2); + expect(results[3].get("number")).toEqual(1); + expect(results[0].get("string")).toEqual("a"); + expect(results[1].get("string")).toEqual("c"); + expect(results[2].get("string")).toEqual("d"); + expect(results[3].get("string")).toEqual("b"); }); - it('can query offline limit', async () => { + it("can query offline limit", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", number: 3, - string: 'a', + string: "a", }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", number: 1, - string: 'b', + 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'); + let q = new ParseQuery("Item"); q.limit(0); q.fromLocalDatastore(); let results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(2); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(3); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(-1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); }); - it('can query offline skip', async () => { + it("can query offline skip", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", password: 123, number: 3, - string: 'a', + string: "a", }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", number: 1, - string: 'b', + string: "b", }; const obj3 = { - className: 'Item', - objectId: 'objectId3', + className: "Item", + objectId: "objectId3", number: 2, - string: 'c', + string: "c", }; 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'); + let q = new ParseQuery("Item"); q.skip(0); q.fromLocalDatastore(); let results = await q.find(); expect(results.length).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.skip(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.skip(3); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(0); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.skip(4); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(0); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(1); q.skip(2); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(1); q.skip(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(2); q.skip(1); q.fromLocalDatastore(); @@ -3521,39 +3568,37 @@ describe('ParseQuery LocalDatastore', () => { expect(results.length).toEqual(2); }); - it('can query offline withCount, skip and limit', async () => { + it("can query offline withCount, skip and limit", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', + className: "Item", + objectId: "objectId1", password: 123, number: 3, - string: 'a', + string: "a", }; const obj2 = { - className: 'Item', - objectId: 'objectId2', + className: "Item", + objectId: "objectId2", number: 1, - string: 'b', + string: "b", }; const obj3 = { - className: 'Item', - objectId: 'objectId3', + className: "Item", + objectId: "objectId3", number: 2, - string: 'c', + string: "c", }; 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'); + let q = new ParseQuery("Item"); q.skip(0); q.withCount(true); q.fromLocalDatastore(); @@ -3561,7 +3606,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(3); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.skip(1); q.withCount(true); q.fromLocalDatastore(); @@ -3569,7 +3614,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(2); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.skip(3); q.withCount(true); q.fromLocalDatastore(); @@ -3577,7 +3622,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(0); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.withCount(true); q.skip(4); q.fromLocalDatastore(); @@ -3585,7 +3630,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(0); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(1); q.skip(2); q.withCount(true); @@ -3594,7 +3639,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(1); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(1); q.skip(1); q.withCount(true); @@ -3603,7 +3648,7 @@ describe('ParseQuery LocalDatastore', () => { expect(result.results.length).toEqual(1); expect(result.count).toEqual(3); - q = new ParseQuery('Item'); + q = new ParseQuery("Item"); q.limit(2); q.skip(1); q.withCount(true); @@ -3613,149 +3658,163 @@ describe('ParseQuery LocalDatastore', () => { expect(result.count).toEqual(3); }); - it('can query offline select keys', async () => { + it("can query offline select keys", async () => { const obj1 = { - className: 'Item', - objectId: 'objectId1', - foo: 'baz', + className: "Item", + objectId: "objectId1", + foo: "baz", 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'); + const q = new ParseQuery("Item"); + q.select("foo"); q.fromLocalDatastore(); const results = await q.find(); - expect(results[0].get('foo')).toEqual('baz'); + expect(results[0].get("foo")).toEqual("baz"); }); - it('can subscribe to query if client is already open', async () => { + it("can subscribe to query if client is already open", async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return false; }, - subscribe: function(query, sessionToken) { - const subscription = new LiveQuerySubscription('0', query, sessionToken); + subscribe: function (query, sessionToken) { + const subscription = new LiveQuerySubscription( + "0", + query, + sessionToken + ); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set('UserController', { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); - CoreManager.set('LiveQueryController', { + CoreManager.set("LiveQueryController", { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); - const query = new ParseQuery('TestObject'); + const query = new ParseQuery("TestObject"); const subscription = await query.subscribe(); - expect(subscription.id).toBe('0'); - expect(subscription.sessionToken).toBe('token'); + expect(subscription.id).toBe("0"); + expect(subscription.sessionToken).toBe("token"); expect(subscription.query).toEqual(query); }); - it('can subscribe to query if client is not open', async () => { + 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) { - const subscription = new LiveQuerySubscription('0', query, sessionToken); + open: function () {}, + subscribe: function (query, sessionToken) { + const subscription = new LiveQuerySubscription( + "0", + query, + sessionToken + ); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set('UserController', { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return 'token'; - } + return "token"; + }, }); - } + }, }); - CoreManager.set('LiveQueryController', { + CoreManager.set("LiveQueryController", { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); - const query = new ParseQuery('TestObject'); + const query = new ParseQuery("TestObject"); const subscription = await query.subscribe(); - expect(subscription.id).toBe('0'); - expect(subscription.sessionToken).toBe('token'); + expect(subscription.id).toBe("0"); + expect(subscription.sessionToken).toBe("token"); expect(subscription.query).toEqual(query); }); - it('can subscribe to query without sessionToken', async () => { + it("can subscribe to query without sessionToken", async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return true; }, - open: function() {}, - subscribe: function(query, sessionToken) { - const subscription = new LiveQuerySubscription('0', query, sessionToken); + open: function () {}, + subscribe: function (query, sessionToken) { + const subscription = new LiveQuerySubscription( + "0", + query, + sessionToken + ); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set('UserController', { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve(null); - } + }, }); - CoreManager.set('LiveQueryController', { + CoreManager.set("LiveQueryController", { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); - const query = new ParseQuery('TestObject'); + const query = new ParseQuery("TestObject"); const subscription = await query.subscribe(); - expect(subscription.id).toBe('0'); + expect(subscription.id).toBe("0"); expect(subscription.sessionToken).toBeUndefined(); expect(subscription.query).toEqual(query); }); - it('can subscribe to query with sessionToken parameter', async () => { + it("can subscribe to query with sessionToken parameter", async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return true; }, - open: function() {}, - subscribe: function(query, sessionToken) { - const subscription = new LiveQuerySubscription('0', query, sessionToken); + open: function () {}, + subscribe: function (query, sessionToken) { + const subscription = new LiveQuerySubscription( + "0", + query, + sessionToken + ); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set('UserController', { + CoreManager.set("UserController", { currentUserAsync() { return Promise.resolve(null); - } + }, }); - CoreManager.set('LiveQueryController', { + CoreManager.set("LiveQueryController", { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); - const query = new ParseQuery('TestObject'); - const subscription = await query.subscribe('r:test'); - expect(subscription.id).toBe('0'); - expect(subscription.sessionToken).toBe('r:test'); + const query = new ParseQuery("TestObject"); + const subscription = await query.subscribe("r:test"); + expect(subscription.id).toBe("0"); + expect(subscription.sessionToken).toBe("r:test"); expect(subscription.query).toEqual(query); }); }); diff --git a/src/__tests__/ParseRelation-test.js b/src/__tests__/ParseRelation-test.js index 7c226eeb1..d6d2986cb 100644 --- a/src/__tests__/ParseRelation-test.js +++ b/src/__tests__/ParseRelation-test.js @@ -7,17 +7,17 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../encode'); -jest.dontMock('../ParseRelation'); -jest.dontMock('../ParseOp'); -jest.dontMock('../unique'); +jest.dontMock("../encode"); +jest.dontMock("../ParseRelation"); +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; @@ -50,11 +50,11 @@ mockObject.prototype = { finalOp = mockStore[this.id][key][i].mergeWith(finalOp); } return finalOp; - } + }, }; -jest.setMock('../ParseObject', mockObject); +jest.setMock("../ParseObject", mockObject); -const mockQuery = function(className) { +const mockQuery = function (className) { this.className = className; this.where = {}; this._extraOptions = {}; @@ -63,240 +63,240 @@ mockQuery.prototype = { _addCondition(key, comparison, value) { this.where[key] = this.where[key] || {}; this.where[key][comparison] = value; - } + }, }; -jest.setMock('../ParseQuery', mockQuery); +jest.setMock("../ParseQuery", mockQuery); -const ParseObject = require('../ParseObject'); -const ParseRelation = require('../ParseRelation').default; +const ParseObject = require("../ParseObject"); +const ParseRelation = require("../ParseRelation").default; -describe('ParseRelation', () => { - it('can be constructed with a reference parent and key', () => { - const parent = new ParseObject('Item'); - parent.id = 'I1'; - const r = new ParseRelation(parent, 'shipments'); +describe("ParseRelation", () => { + it("can be constructed with a reference parent and key", () => { + const parent = new ParseObject("Item"); + parent.id = "I1"; + const r = new ParseRelation(parent, "shipments"); expect(r.parent).toBe(parent); - expect(r.key).toBe('shipments'); + expect(r.key).toBe("shipments"); expect(r.targetClassName).toBe(null); }); - it('can add objects to a relation', () => { - const parent = new ParseObject('Item'); - parent.id = 'I1'; - const r = new ParseRelation(parent, 'shipments'); - const o = new ParseObject('Delivery'); - o.id = 'D1'; + it("can add objects to a relation", () => { + const parent = new ParseObject("Item"); + parent.id = "I1"; + const r = new ParseRelation(parent, "shipments"); + const o = new ParseObject("Delivery"); + o.id = "D1"; const p = r.add(o); expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'AddRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' } - ] + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "AddRelation", + objects: [{ __type: "Pointer", objectId: "D1", className: "Delivery" }], }); - const o2 = new ParseObject('Delivery'); - o2.id = 'D2'; - const o3 = new ParseObject('Delivery'); - o3.id = 'D3'; + const o2 = new ParseObject("Delivery"); + o2.id = "D2"; + const o3 = new ParseObject("Delivery"); + o3.id = "D3"; r.add([o2, o3]); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'AddRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "AddRelation", objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, - { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, - { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, - ] + { __type: "Pointer", objectId: "D1", className: "Delivery" }, + { __type: "Pointer", objectId: "D2", className: "Delivery" }, + { __type: "Pointer", objectId: "D3", className: "Delivery" }, + ], }); }); - it('can add empty array to a relation', () => { - const parent = new ParseObject('Item'); - parent.id = 'I1234'; - const r = new ParseRelation(parent, 'shipments'); - const o = new ParseObject('Delivery'); - o.id = 'D1234'; + it("can add empty array to a relation", () => { + const parent = new ParseObject("Item"); + parent.id = "I1234"; + const r = new ParseRelation(parent, "shipments"); + const o = new ParseObject("Delivery"); + o.id = "D1234"; const p = r.add(o); expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'AddRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "AddRelation", objects: [ - { __type: 'Pointer', objectId: 'D1234', className: 'Delivery' } - ] + { __type: "Pointer", objectId: "D1234", className: "Delivery" }, + ], }); // Adding empty array shouldn't change the relation r.add([]); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'AddRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "AddRelation", objects: [ - { __type: 'Pointer', objectId: 'D1234', className: 'Delivery' } - ] + { __type: "Pointer", objectId: "D1234", className: "Delivery" }, + ], }); }); - it('cannot add to relation without parent', () => { + it("cannot add to relation without parent", () => { 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', () => { + 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', () => { + 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', () => { - const parent = new ParseObject('Item'); - parent.id = 'I2'; - const r = new ParseRelation(parent, 'shipments'); - const o = new ParseObject('Delivery'); - o.id = 'D1'; + it("can remove objects from a relation", () => { + const parent = new ParseObject("Item"); + parent.id = "I2"; + const r = new ParseRelation(parent, "shipments"); + const o = new ParseObject("Delivery"); + o.id = "D1"; r.remove(o); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'RemoveRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' } - ] + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "RemoveRelation", + objects: [{ __type: "Pointer", objectId: "D1", className: "Delivery" }], }); - const o2 = new ParseObject('Delivery'); - o2.id = 'D2'; - const o3 = new ParseObject('Delivery'); - o3.id = 'D3'; + const o2 = new ParseObject("Delivery"); + o2.id = "D2"; + const o3 = new ParseObject("Delivery"); + o3.id = "D3"; r.remove([o2, o3]); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'RemoveRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "RemoveRelation", objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, - { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, - { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, - ] + { __type: "Pointer", objectId: "D1", className: "Delivery" }, + { __type: "Pointer", objectId: "D2", className: "Delivery" }, + { __type: "Pointer", objectId: "D3", className: "Delivery" }, + ], }); }); - it('can remove empty array from a relation', () => { - const parent = new ParseObject('Item'); - parent.id = 'I5678'; - const r = new ParseRelation(parent, 'shipments'); - const o = new ParseObject('Delivery'); - o.id = 'D5678'; + it("can remove empty array from a relation", () => { + const parent = new ParseObject("Item"); + parent.id = "I5678"; + const r = new ParseRelation(parent, "shipments"); + const o = new ParseObject("Delivery"); + o.id = "D5678"; r.remove(o); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'RemoveRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "RemoveRelation", objects: [ - { __type: 'Pointer', objectId: 'D5678', className: 'Delivery' } - ] + { __type: "Pointer", objectId: "D5678", className: "Delivery" }, + ], }); // Removing empty array shouldn't change the relation r.remove([]); expect(r.toJSON()).toEqual({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(parent.op('shipments').toJSON()).toEqual({ - __op: 'RemoveRelation', + expect(parent.op("shipments").toJSON()).toEqual({ + __op: "RemoveRelation", objects: [ - { __type: 'Pointer', objectId: 'D5678', className: 'Delivery' } - ] + { __type: "Pointer", objectId: "D5678", className: "Delivery" }, + ], }); }); - it('can generate a query for relation objects', () => { - const parent = new ParseObject('Item'); - parent.id = 'I1'; - let r = new ParseRelation(parent, 'shipments'); + it("can generate a query for relation objects", () => { + const parent = new ParseObject("Item"); + parent.id = "I1"; + let r = new ParseRelation(parent, "shipments"); let q = r.query(); - expect(q.className).toBe('Item'); + 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' + __type: "Pointer", + objectId: "I1", + className: "Item", }, - key: 'shipments' - } + key: "shipments", + }, }); - r = new ParseRelation(parent, 'shipments'); - const o = new ParseObject('Delivery'); - o.id = 'D1'; + r = new ParseRelation(parent, "shipments"); + const o = new ParseObject("Delivery"); + o.id = "D1"; r.add(o); q = r.query(); - expect(q.className).toBe('Delivery'); + expect(q.className).toBe("Delivery"); expect(q.where).toEqual({ $relatedTo: { object: { - __type: 'Pointer', - className: 'Item', - objectId: 'I1' + __type: "Pointer", + className: "Item", + objectId: "I1", }, - key: 'shipments' - } + key: "shipments", + }, }); }); - it('can ensure it relates to the correct parent and key', () => { - 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.'); + it("can ensure it relates to the correct parent and key", () => { + 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(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(); + 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); noParent._ensureParentAndKey(parent); expect(noParent.parent).toEqual(parent); - const noIdParent = new ParseObject('Item'); - const newParent = new ParseObject('Item'); - newParent.id = 'newId'; + const noIdParent = new ParseObject("Item"); + const newParent = new ParseObject("Item"); + newParent.id = "newId"; const hasParent = new ParseRelation(noIdParent); hasParent._ensureParentAndKey(newParent); diff --git a/src/__tests__/ParseRole-test.js b/src/__tests__/ParseRole-test.js index 090a544fc..00e436832 100644 --- a/src/__tests__/ParseRole-test.js +++ b/src/__tests__/ParseRole-test.js @@ -7,92 +7,103 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParseRole'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParseRole"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../UniqueInstanceStateController"); -const ParseACL = require('../ParseACL').default; -const ParseError = require('../ParseError').default; -const ParseObject = require('../ParseObject').default; -const ParseRelation = require('../ParseRelation').default; -const ParseRole = require('../ParseRole').default; +const ParseACL = require("../ParseACL").default; +const ParseError = require("../ParseError").default; +const ParseObject = require("../ParseObject").default; +const ParseRelation = require("../ParseRelation").default; +const ParseRole = require("../ParseRole").default; -describe('ParseRole', () => { +describe("ParseRole", () => { beforeEach(() => { ParseObject.disableSingleInstance(); }); - it('can create Roles', () => { + it("can create Roles", () => { let role = new ParseRole(); expect(role.getName()).toBe(undefined); expect(role.getACL()).toBe(null); const acl = new ParseACL({ aUserId: { read: true, write: true } }); - role = new ParseRole('admin', acl); - expect(role.getName()).toBe('admin'); + role = new ParseRole("admin", acl); + expect(role.getName()).toBe("admin"); expect(role.getACL()).toBe(acl); }); - it('handle non string name', () => { + it("handle non string name", () => { const role = new ParseRole(); role.get = () => 1234; - expect(role.getName()).toBe(''); + expect(role.getName()).toBe(""); }); - it('can validate attributes', () => { + it("can validate attributes", () => { 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.' - )); + 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." + ) + ); 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); }); - it('can be constructed from JSON', () => { + it("can be constructed from JSON", () => { const role = ParseObject.fromJSON({ - className: '_Role', - objectId: '102', - name: 'admin' + className: "_Role", + objectId: "102", + name: "admin", }); expect(role instanceof ParseObject).toBe(true); expect(role instanceof ParseRole).toBe(true); - expect(role.getName()).toBe('admin'); + expect(role.getName()).toBe("admin"); }); - it('can get relations', () => { + it("can get relations", () => { const role = new ParseRole(); expect(role.getUsers() instanceof ParseRelation).toBe(true); expect(role.getRoles() instanceof ParseRelation).toBe(true); diff --git a/src/__tests__/ParseSchema-test.js b/src/__tests__/ParseSchema-test.js index 04d88aa80..86a1622b8 100644 --- a/src/__tests__/ParseSchema-test.js +++ b/src/__tests__/ParseSchema-test.js @@ -8,40 +8,40 @@ */ 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', + __type: "Pointer", objectId: this.id, - } + }; }; }; -jest.setMock('../ParseObject', mockObject); +jest.setMock("../ParseObject", mockObject); -const ParseObject = require('../ParseObject'); -const ParseSchema = require('../ParseSchema').default; -const CoreManager = require('../CoreManager'); +const ParseObject = require("../ParseObject"); +const ParseSchema = require("../ParseSchema").default; +const CoreManager = require("../CoreManager"); const defaultController = CoreManager.getSchemaController(); -describe('ParseSchema', () => { - it('can create schema', (done) => { - const schema = new ParseSchema('SchemaTest'); - expect(schema.className).toEqual('SchemaTest'); +describe("ParseSchema", () => { + it("can create schema", (done) => { + const schema = new ParseSchema("SchemaTest"); + expect(schema.className).toEqual("SchemaTest"); done(); }); - it('can create schema with User Class', (done) => { - const schema = new ParseSchema('User'); - expect(schema.className).toEqual('_User'); + 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,72 +50,89 @@ describe('ParseSchema', () => { } }); - it('can create schema fields', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("can create schema fields", (done) => { + const schema = new ParseSchema("SchemaTest"); schema - .addField('defaultFieldString') - .addString('stringField') - .addNumber('numberField') - .addBoolean('booleanField') - .addDate('dateField') - .addFile('fileField') - .addGeoPoint('geoPointField') - .addPolygon('polygonField') - .addArray('arrayField') - .addObject('objectField') - .addPointer('pointerField', '_User') - .addRelation('relationField', '_User'); - - expect(schema._fields.defaultFieldString.type).toEqual('String'); - expect(schema._fields.stringField.type).toEqual('String'); - expect(schema._fields.numberField.type).toEqual('Number'); - expect(schema._fields.booleanField.type).toEqual('Boolean'); - expect(schema._fields.dateField.type).toEqual('Date'); - expect(schema._fields.fileField.type).toEqual('File'); - expect(schema._fields.geoPointField.type).toEqual('GeoPoint'); - expect(schema._fields.polygonField.type).toEqual('Polygon'); - expect(schema._fields.arrayField.type).toEqual('Array'); - expect(schema._fields.objectField.type).toEqual('Object'); - expect(schema._fields.pointerField.type).toEqual('Pointer'); - expect(schema._fields.relationField.type).toEqual('Relation'); - expect(schema._fields.pointerField.targetClass).toEqual('_User'); - expect(schema._fields.relationField.targetClass).toEqual('_User'); + .addField("defaultFieldString") + .addString("stringField") + .addNumber("numberField") + .addBoolean("booleanField") + .addDate("dateField") + .addFile("fileField") + .addGeoPoint("geoPointField") + .addPolygon("polygonField") + .addArray("arrayField") + .addObject("objectField") + .addPointer("pointerField", "_User") + .addRelation("relationField", "_User"); + + expect(schema._fields.defaultFieldString.type).toEqual("String"); + expect(schema._fields.stringField.type).toEqual("String"); + expect(schema._fields.numberField.type).toEqual("Number"); + expect(schema._fields.booleanField.type).toEqual("Boolean"); + expect(schema._fields.dateField.type).toEqual("Date"); + expect(schema._fields.fileField.type).toEqual("File"); + expect(schema._fields.geoPointField.type).toEqual("GeoPoint"); + expect(schema._fields.polygonField.type).toEqual("Polygon"); + expect(schema._fields.arrayField.type).toEqual("Array"); + expect(schema._fields.objectField.type).toEqual("Object"); + expect(schema._fields.pointerField.type).toEqual("Pointer"); + expect(schema._fields.relationField.type).toEqual("Relation"); + expect(schema._fields.pointerField.targetClass).toEqual("_User"); + expect(schema._fields.relationField.targetClass).toEqual("_User"); done(); }); - it('can create schema fields required and default values', () => { - const object = new ParseObject('TestObject', '1234'); - const schema = new ParseSchema('SchemaTest'); + it("can create schema fields required and default values", () => { + 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() }); - - expect(schema._fields.defaultFieldString.type).toEqual('String'); + .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); - expect(schema._fields.defaultFieldString.defaultValue).toEqual('hello'); - expect(schema._fields.pointerField.type).toEqual('Pointer'); - expect(schema._fields.pointerField.targetClass).toEqual('TestObject'); + expect(schema._fields.defaultFieldString.defaultValue).toEqual("hello"); + expect(schema._fields.pointerField.type).toEqual("Pointer"); + expect(schema._fields.pointerField.targetClass).toEqual("TestObject"); expect(schema._fields.pointerField.required).toEqual(true); - expect(schema._fields.pointerField.defaultValue).toEqual(object.toPointer()); + expect(schema._fields.pointerField.defaultValue).toEqual( + object.toPointer() + ); expect(schema._fields.dateField).toEqual({ - type: 'Date', + 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) => { - const schema = new ParseSchema('SchemaTest'); - schema.addIndex('testIndex', { name: 1 }); + it("can create schema indexes", (done) => { + const schema = new ParseSchema("SchemaTest"); + schema.addIndex("testIndex", { name: 1 }); expect(schema._indexes.testIndex.name).toBe(1); done(); }); - it('can set schema class level permissions', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("can set schema class level permissions", (done) => { + const schema = new ParseSchema("SchemaTest"); expect(schema._clp).toBeUndefined(); schema.setCLP(undefined); expect(schema._clp).toBeUndefined(); @@ -125,104 +142,104 @@ describe('ParseSchema', () => { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { '*': true }, + create: { "*": true }, 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'); + const schema = new ParseSchema("SchemaTest"); + schema.addField(null, "string"); } catch (e) { done(); } }); - 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'); + const schema = new ParseSchema("SchemaTest"); + schema.addField("testField", "unknown"); } catch (e) { done(); } }); - 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}); + const schema = new ParseSchema("SchemaTest"); + 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); + const schema = new ParseSchema("SchemaTest"); + schema.addIndex("testIndex", null); } catch (e) { done(); } }); - 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'); + const schema = new ParseSchema("SchemaTest"); + schema.addPointer(null, "targetClass"); } catch (e) { done(); } }); - 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); + const schema = new ParseSchema("SchemaTest"); + schema.addPointer("pointerField", null); } catch (e) { done(); } }); - 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'); + const schema = new ParseSchema("SchemaTest"); + schema.addRelation(null, "targetClass"); } catch (e) { done(); } }); - 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); + const schema = new ParseSchema("SchemaTest"); + schema.addRelation("relationField", null); } catch (e) { done(); } }); - it('can delete schema field', (done) => { - const schema = new ParseSchema('SchemaTest'); - schema.deleteField('testField'); - expect(schema._fields.testField).toEqual({ __op: 'Delete'}); + it("can delete schema field", (done) => { + const schema = new ParseSchema("SchemaTest"); + schema.deleteField("testField"); + expect(schema._fields.testField).toEqual({ __op: "Delete" }); done(); }); - it('can delete schema index', (done) => { - const schema = new ParseSchema('SchemaTest'); - schema.deleteIndex('testIndex'); - expect(schema._indexes.testIndex).toEqual({ __op: 'Delete'}); + it("can delete schema index", (done) => { + const schema = new ParseSchema("SchemaTest"); + schema.deleteIndex("testIndex"); + expect(schema._indexes.testIndex).toEqual({ __op: "Delete" }); done(); }); - it('can save schema', (done) => { + it("can save schema", (done) => { CoreManager.setSchemaController({ send() {}, get() {}, @@ -230,26 +247,26 @@ describe('ParseSchema', () => { delete() {}, purge() {}, create(className, params) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); expect(params).toEqual({ - className: 'SchemaTest', - fields: { name: { type: 'String'} }, - indexes: { testIndex: { name: 1 } } + className: "SchemaTest", + fields: { name: { type: "String" } }, + indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, }); - const schema = new ParseSchema('SchemaTest'); - schema.addField('name'); - schema.addIndex('testIndex', {'name': 1}); + const schema = new ParseSchema("SchemaTest"); + schema.addField("name"); + 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() {}, @@ -257,26 +274,26 @@ describe('ParseSchema', () => { delete() {}, purge() {}, update(className, params) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); expect(params).toEqual({ - className: 'SchemaTest', - fields: { name: { type: 'String'} }, - indexes: { testIndex: { name: 1 } } + className: "SchemaTest", + fields: { name: { type: "String" } }, + indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, }); - const schema = new ParseSchema('SchemaTest'); - schema.addField('name'); - schema.addIndex('testIndex', {'name': 1}); + const schema = new ParseSchema("SchemaTest"); + schema.addField("name"); + 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() {}, @@ -284,19 +301,19 @@ describe('ParseSchema', () => { get() {}, purge() {}, delete(className) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); return Promise.resolve([]); }, }); - const schema = new ParseSchema('SchemaTest'); + const schema = new ParseSchema("SchemaTest"); schema.delete().then((results) => { expect(results).toEqual([]); done(); }); }); - it('can purge schema', (done) => { + it("can purge schema", (done) => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -304,19 +321,19 @@ describe('ParseSchema', () => { get() {}, delete() {}, purge(className) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); return Promise.resolve([]); }, }); - const schema = new ParseSchema('SchemaTest'); + const schema = new ParseSchema("SchemaTest"); schema.purge().then((results) => { expect(results).toEqual([]); done(); }); }); - it('can get schema', (done) => { + it("can get schema", (done) => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -324,19 +341,19 @@ describe('ParseSchema', () => { delete() {}, purge() {}, get(className) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); return Promise.resolve([]); }, }); - const schema = new ParseSchema('SchemaTest'); + const schema = new ParseSchema("SchemaTest"); schema.get().then((results) => { expect(results).toEqual([]); done(); }); }); - it('cannot get empty schema', (done) => { + it("cannot get empty schema", (done) => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -344,23 +361,26 @@ describe('ParseSchema', () => { delete() {}, purge() {}, get(className) { - expect(className).toBe('SchemaTest'); + expect(className).toBe("SchemaTest"); return Promise.resolve(null); }, }); - 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(); - }); + 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(); + } + ); }); - it('can get all schema', (done) => { + it("can get all schema", (done) => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -368,20 +388,20 @@ describe('ParseSchema', () => { delete() {}, purge() {}, get(className) { - expect(className).toBe(''); + expect(className).toBe(""); return Promise.resolve({ - results: ['all'] + results: ["all"], }); }, }); ParseSchema.all().then((results) => { - expect(results[0]).toEqual('all'); + 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() {}, @@ -389,70 +409,73 @@ describe('ParseSchema', () => { delete() {}, purge() {}, get(className) { - expect(className).toBe(''); + 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', () => { +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) => { - const schema = new ParseSchema('SchemaTest'); + it("save schema", (done) => { + const schema = new ParseSchema("SchemaTest"); schema.save().then((results) => { expect(results).toEqual([]); done(); }); }); - it('get schema', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("get schema", (done) => { + const schema = new ParseSchema("SchemaTest"); schema.get().then((results) => { expect(results).toEqual([]); done(); }); }); - it('update schema', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("update schema", (done) => { + const schema = new ParseSchema("SchemaTest"); schema.update().then((results) => { expect(results).toEqual([]); done(); }); }); - it('delete schema', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("delete schema", (done) => { + const schema = new ParseSchema("SchemaTest"); schema.delete().then((results) => { expect(results).toEqual([]); done(); }); }); - it('purge schema', (done) => { - const schema = new ParseSchema('SchemaTest'); + it("purge schema", (done) => { + const schema = new ParseSchema("SchemaTest"); schema.purge().then((results) => { expect(results).toEqual([]); done(); diff --git a/src/__tests__/ParseSession-test.js b/src/__tests__/ParseSession-test.js index 0f278350d..5706fad8b 100644 --- a/src/__tests__/ParseSession-test.js +++ b/src/__tests__/ParseSession-test.js @@ -7,151 +7,157 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../isRevocableSession'); -jest.dontMock('../ObjectStateMutations') -jest.dontMock('../parseDate'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParseSession'); -jest.dontMock('../RESTController'); -jest.dontMock('../Storage'); -jest.dontMock('../StorageController.default'); -jest.dontMock('../TaskQueue'); -jest.dontMock('../unique'); -jest.dontMock('../UniqueInstanceStateController'); - -jest.dontMock('./test_helpers/mockXHR'); - -const mockUser = function(token) { +jest.dontMock("../CoreManager"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../isRevocableSession"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../parseDate"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParseSession"); +jest.dontMock("../RESTController"); +jest.dontMock("../Storage"); +jest.dontMock("../StorageController.default"); +jest.dontMock("../TaskQueue"); +jest.dontMock("../unique"); +jest.dontMock("../UniqueInstanceStateController"); + +jest.dontMock("./test_helpers/mockXHR"); + +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); +jest.setMock("../ParseUser", mockUser); -const CoreManager = require('../CoreManager'); -const ParseObject = require('../ParseObject').default; -const ParseSession = require('../ParseSession').default; +const CoreManager = require("../CoreManager"); +const ParseObject = require("../ParseObject").default; +const ParseSession = require("../ParseSession").default; -CoreManager.set('APPLICATION_ID', 'A'); -CoreManager.set('JAVASCRIPT_KEY', 'B'); +CoreManager.set("APPLICATION_ID", "A"); +CoreManager.set("JAVASCRIPT_KEY", "B"); -describe('ParseSession', () => { - it('can be initialized', () => { +describe("ParseSession", () => { + it("can be initialized", () => { let session = new ParseSession(); - session.set('someField', 'someValue'); - expect(session.getSessionToken()).toBe(''); - expect(session.get('someField')).toBe('someValue'); + session.set("someField", "someValue"); + expect(session.getSessionToken()).toBe(""); + expect(session.get("someField")).toBe("someValue"); session = new ParseSession({ - someField: 'someValue' + someField: "someValue", }); - expect(session.get('someField')).toBe('someValue'); + expect(session.get("someField")).toBe("someValue"); }); - it('cannot create schema with invalid fields', () => { + 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"); }); - it('cannot write to readonly fields', () => { + it("cannot write to readonly fields", () => { const session = new ParseSession(); - expect(session.set.bind(session, 'createdWith', 'facebook')).toThrow( - 'Cannot modify readonly attribute: createdWith' + expect(session.set.bind(session, "createdWith", "facebook")).toThrow( + "Cannot modify readonly attribute: createdWith" ); - expect(session.set.bind(session, 'expiresAt', new Date())).toThrow( - 'Cannot modify readonly attribute: expiresAt' + expect(session.set.bind(session, "expiresAt", new Date())).toThrow( + "Cannot modify readonly attribute: expiresAt" ); - expect(session.set.bind(session, 'installationId', 'iid')).toThrow( - 'Cannot modify readonly attribute: installationId' + expect(session.set.bind(session, "installationId", "iid")).toThrow( + "Cannot modify readonly attribute: installationId" ); - expect(session.set.bind(session, 'restricted', true)).toThrow( - 'Cannot modify readonly attribute: restricted' + expect(session.set.bind(session, "restricted", true)).toThrow( + "Cannot modify readonly attribute: restricted" ); - expect(session.set.bind(session, 'sessionToken', 'st')).toThrow( - 'Cannot modify readonly attribute: sessionToken' + expect(session.set.bind(session, "sessionToken", "st")).toThrow( + "Cannot modify readonly attribute: sessionToken" ); - expect(session.set.bind(session, 'user', null)).toThrow( - 'Cannot modify readonly attribute: user' + expect(session.set.bind(session, "user", null)).toThrow( + "Cannot modify readonly attribute: user" ); }); - it('exposes the token through a getter', () => { + it("exposes the token through a getter", () => { const session = new ParseSession(); session._finishFetch({ - id: 'session1', - sessionToken: 'abc123' + id: "session1", + sessionToken: "abc123", }); - expect(session.getSessionToken()).toBe('abc123'); + expect(session.getSessionToken()).toBe("abc123"); }); - it('checks the current user for a revocable token', () => { + 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'); - expect(path).toBe('sessions/me'); + expect(method).toBe("GET"); + expect(path).toBe("sessions/me"); expect(options).toEqual({ - sessionToken: 'abc123', + sessionToken: "abc123", useMasterKey: true, }); return Promise.resolve({ - objectId: 'session1', - sessionToken: 'abc123' + objectId: "session1", + sessionToken: "abc123", }); }, - ajax() {} + ajax() {}, }); - mockUser.currentAsync = function() { - return Promise.resolve(new mockUser('abc123')); + mockUser.currentAsync = function () { + return Promise.resolve(new mockUser("abc123")); }; ParseSession.current({ useMasterKey: true }).then((session) => { expect(session instanceof ParseSession).toBe(true); - expect(session.id).toBe('session1'); - expect(session.getSessionToken()).toBe('abc123'); + expect(session.id).toBe("session1"); + expect(session.getSessionToken()).toBe("abc123"); done(); }); }); - 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.') + expect(error).toBe("There is no current user."); done(); }); }); - it('can be cloned', () => { + it("can be cloned", () => { const s = ParseObject.fromJSON({ - className: '_Session', - sessionToken: '123abc', - foo: 12 + className: "_Session", + sessionToken: "123abc", + foo: 12, }); const clone = s.clone(); - expect(clone.className).toBe('_Session'); - expect(clone.get('foo')).toBe(12); - expect(clone.get('sessionToken')).toBe(undefined); + expect(clone.className).toBe("_Session"); + expect(clone.get("foo")).toBe(12); + expect(clone.get("sessionToken")).toBe(undefined); }); }); diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index fce28b737..857272769 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -7,896 +7,997 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../AnonymousUtils'); -jest.dontMock('../CoreManager'); -jest.dontMock('../CryptoController'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../isRevocableSession'); -jest.dontMock('../LocalDatastore'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../parseDate'); -jest.dontMock('../ParseError'); -jest.dontMock('../ParseObject'); -jest.dontMock('../ParseOp'); -jest.dontMock('../ParseUser'); -jest.dontMock('../promiseUtils'); -jest.dontMock('../RESTController'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../Storage'); -jest.dontMock('../StorageController.default'); -jest.dontMock('../TaskQueue'); -jest.dontMock('../unique'); -jest.dontMock('../UniqueInstanceStateController'); -jest.dontMock('crypto-js/aes'); -jest.dontMock('crypto-js/enc-utf8'); - -jest.mock('uuid/v4', () => { +jest.dontMock("../AnonymousUtils"); +jest.dontMock("../CoreManager"); +jest.dontMock("../CryptoController"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../isRevocableSession"); +jest.dontMock("../LocalDatastore"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../parseDate"); +jest.dontMock("../ParseError"); +jest.dontMock("../ParseObject"); +jest.dontMock("../ParseOp"); +jest.dontMock("../ParseUser"); +jest.dontMock("../promiseUtils"); +jest.dontMock("../RESTController"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../Storage"); +jest.dontMock("../StorageController.default"); +jest.dontMock("../TaskQueue"); +jest.dontMock("../unique"); +jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock("crypto-js/aes"); +jest.dontMock("crypto-js/enc-utf8"); + +jest.mock("uuid/v4", () => { let value = 0; return () => value++; }); -jest.dontMock('./test_helpers/mockXHR'); -jest.dontMock('./test_helpers/mockAsyncStorage'); - -const mockAsyncStorage = require('./test_helpers/mockAsyncStorage'); -const CoreManager = require('../CoreManager'); -const CryptoController = require('../CryptoController'); -const LocalDatastore = require('../LocalDatastore'); -const ParseObject = require('../ParseObject').default; -const ParseUser = require('../ParseUser').default; -const Storage = require('../Storage'); -const ParseError = require('../ParseError').default; -const AnonymousUtils = require('../AnonymousUtils').default; - -CoreManager.set('APPLICATION_ID', 'A'); -CoreManager.set('JAVASCRIPT_KEY', 'B'); +jest.dontMock("./test_helpers/mockXHR"); +jest.dontMock("./test_helpers/mockAsyncStorage"); + +const mockAsyncStorage = require("./test_helpers/mockAsyncStorage"); +const CoreManager = require("../CoreManager"); +const CryptoController = require("../CryptoController"); +const LocalDatastore = require("../LocalDatastore"); +const ParseObject = require("../ParseObject").default; +const ParseUser = require("../ParseUser").default; +const Storage = require("../Storage"); +const ParseError = require("../ParseError").default; +const AnonymousUtils = require("../AnonymousUtils").default; + +CoreManager.set("APPLICATION_ID", "A"); +CoreManager.set("JAVASCRIPT_KEY", "B"); CoreManager.setCryptoController(CryptoController); function flushPromises() { - return new Promise(resolve => setImmediate(resolve)); + return new Promise((resolve) => setImmediate(resolve)); } -describe('ParseUser', () => { +describe("ParseUser", () => { beforeEach(() => { ParseObject.enableSingleInstance(); LocalDatastore._clear(); }); - it('can be constructed with initial attributes', () => { + it("can be constructed with initial attributes", () => { let u = new ParseUser(); expect(u.isCurrent()).toBe(false); - expect(u.className).toBe('_User'); + expect(u.className).toBe("_User"); expect(u instanceof ParseObject).toBe(true); u = new ParseUser({ - username: 'andrew', - password: 'secret' + username: "andrew", + password: "secret", }); - expect(u.get('username')).toBe('andrew'); - expect(u.get('password')).toBe('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', () => { + it("exposes certain attributes through special setters and getters", () => { const u = ParseObject.fromJSON({ - className: '_User', - username: 'user12', - email: 'user12@parse.com', - sessionToken: '123abc' + className: "_User", + username: "user12", + email: "user12@parse.com", + sessionToken: "123abc", }); expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe('user12'); - expect(u.getEmail()).toBe('user12@parse.com'); - expect(u.getSessionToken()).toBe('123abc'); + expect(u.getUsername()).toBe("user12"); + expect(u.getEmail()).toBe("user12@parse.com"); + expect(u.getSessionToken()).toBe("123abc"); const u2 = new ParseUser(); - u2.setUsername('bono'); - u2.setEmail('bono@u2.com'); - expect(u2.getUsername()).toBe('bono'); - expect(u2.getEmail()).toBe('bono@u2.com'); + u2.setUsername("bono"); + u2.setEmail("bono@u2.com"); + expect(u2.getUsername()).toBe("bono"); + expect(u2.getEmail()).toBe("bono@u2.com"); }); - it('can handle invalid setters and getters', () => { + it("can handle invalid setters and getters", () => { const u = ParseObject.fromJSON({ - className: '_User', + className: "_User", username: 123, email: 456, sessionToken: 789, }); expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe(''); - expect(u.getEmail()).toBe(''); - expect(u.getSessionToken()).toBe(''); + expect(u.getUsername()).toBe(""); + expect(u.getEmail()).toBe(""); + expect(u.getSessionToken()).toBe(""); }); - it('can clone User objects', () => { + it("can clone User objects", () => { const u = ParseObject.fromJSON({ - className: '_User', - username: 'user12', - email: 'user12@parse.com', - sessionToken: '123abc' + className: "_User", + username: "user12", + email: "user12@parse.com", + sessionToken: "123abc", }); const clone = u.clone(); - expect(clone.className).toBe('_User'); - expect(clone.get('username')).toBe('user12'); - expect(clone.get('email')).toBe('user12@parse.com'); - expect(clone.get('sessionToken')).toBe(undefined); + expect(clone.className).toBe("_User"); + expect(clone.get("username")).toBe("user12"); + expect(clone.get("email")).toBe("user12@parse.com"); + expect(clone.get("sessionToken")).toBe(undefined); }); - it('can create a new instance of a User', () => { + it("can create a new instance of a User", () => { ParseObject.disableSingleInstance(); const o = ParseObject.fromJSON({ - className: '_User', - objectId: 'U111', - username: 'u111', - email: 'u111@parse.com', - sesionToken: '1313' + className: "_User", + objectId: "U111", + username: "u111", + email: "u111@parse.com", + sesionToken: "1313", }); let o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); - expect(o.get('username')).toBe(o2.get('username')); - expect(o.get('sessionToken')).toBe(o2.get('sessionToken')); + expect(o.get("username")).toBe(o2.get("username")); + expect(o.get("sessionToken")).toBe(o2.get("sessionToken")); expect(o).not.toBe(o2); o.set({ admin: true }); - expect(o2.get('admin')).toBe(undefined); + expect(o2.get("admin")).toBe(undefined); o2 = o.newInstance(); - expect(o2.get('admin')).toBe(true); + expect(o2.get("admin")).toBe(true); ParseObject.enableSingleInstance(); }); - it('makes session tokens readonly', () => { + it("makes session tokens readonly", () => { const u = new ParseUser(); - expect(u.set.bind(u, 'sessionToken', 'token')).toThrow( - 'Cannot modify readonly attribute: sessionToken' + expect(u.set.bind(u, "sessionToken", "token")).toThrow( + "Cannot modify readonly attribute: sessionToken" ); }); - it('does not allow current user actions on node servers', () => { - expect(ParseUser.become.bind(null, 'token')).toThrow( - 'It is not memory-safe to become a user in a server environment' + it("does not allow current user actions on node servers", () => { + expect(ParseUser.become.bind(null, "token")).toThrow( + "It is not memory-safe to become a user in a server environment" ); }); - it('can sign up a new user', (done) => { + it("can sign up a new user", (done) => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('POST'); - expect(path).toBe('users'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid', - }, 201); + expect(method).toBe("POST"); + expect(path).toBe("users"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + 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) => { - expect(u.id).toBe('uid'); - expect(u.get('username')).toBe('username'); - expect(u.get('password')).toBe(undefined); + 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); expect(u.isCurrent()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe('uid'); - expect(current.getUsername()).toBe('username'); - expect(current.get('password')).toBe(undefined); + expect(current.id).toBe("uid"); + expect(current.getUsername()).toBe("username"); + expect(current.get("password")).toBe(undefined); done(); }); }); - it('can log in as a user', (done) => { + it("can log in as a user", (done) => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('GET'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("login"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + return Promise.resolve( + { + objectId: "uid2", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password').then((u) => { - expect(u.id).toBe('uid2'); - expect(u.getSessionToken()).toBe('123abc'); + ParseUser.logIn("username", "password").then((u) => { + expect(u.id).toBe("uid2"); + expect(u.getSessionToken()).toBe("123abc"); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe('uid2'); + expect(current.id).toBe("uid2"); expect(current.authenticated()).toBe(true); done(); }); }); - it('can log in as a user with options', async () => { + it("can log in as a user with options", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); + expect(method).toBe("GET"); + expect(path).toBe("login"); + 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', { + const user = await ParseUser.logIn("username", "password", { useMasterKey: true, - installationId: 'installation1234', + installationId: "installation1234", }); - expect(user.id).toBe('uid2'); + 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({ request(method, path, body) { - expect(method).toBe('POST'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("POST"); + expect(path).toBe("login"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + return Promise.resolve( + { + objectId: "uid2", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password', { usePost: true }).then((u) => { - expect(u.id).toBe('uid2'); - expect(u.getSessionToken()).toBe('123abc'); + ParseUser.logIn("username", "password", { usePost: true }).then((u) => { + expect(u.id).toBe("uid2"); + expect(u.getSessionToken()).toBe("123abc"); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe('uid2'); + expect(current.id).toBe("uid2"); expect(current.authenticated()).toBe(true); done(); }); }); - 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({ request(method, path, body) { - expect(method).toBe('GET'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("login"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + return Promise.resolve( + { + objectId: "uid3", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const u = new ParseUser({ - username: 'username', - password: 'password' + username: "username", + password: "password", }); - u.set('count', 5); + u.set("count", 5); u.logIn().then(() => { - expect(u.id).toBe('uid3'); - expect(u.dirtyKeys()).toEqual(['count']); - expect(u.get('count')).toBe(5); + expect(u.id).toBe("uid3"); + expect(u.dirtyKeys()).toEqual(["count"]); + expect(u.get("count")).toBe(5); done(); }); }); - 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({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('users/me'); - expect(options.sessionToken).toBe('123abc'); - - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("users/me"); + expect(options.sessionToken).toBe("123abc"); + + return Promise.resolve( + { + objectId: "uid3", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.become('123abc').then((u) => { - expect(u.id).toBe('uid3'); + ParseUser.become("123abc").then((u) => { + expect(u.id).toBe("uid3"); expect(u.isCurrent()).toBe(true); expect(u.existed()).toBe(true); done(); }); }); - it('can become a user with async storage', async () => { + it("can become a user with async storage", async () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('users/me'); - expect(options.sessionToken).toBe('123abc'); + expect(method).toBe("GET"); + 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 }); - expect(u.id).toBe('uid3'); + const u = await ParseUser.become("123abc", { useMasterKey: true }); + expect(u.id).toBe("uid3"); expect(u.isCurrent()).toBe(true); expect(u.existed()).toBe(true); CoreManager.setStorageController(currentStorage); }); - it('cannot get synchronous current user with async storage', async () => { + it("cannot get synchronous current user with async storage", async () => { const StorageController = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); ParseUser.enableUnsafeCurrentUser(); 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 () => { + it("can hydrate a user with sessionToken in server environment", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); const user = await ParseUser.hydrate({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc', + objectId: "uid3", + username: "username", + sessionToken: "123abc", }); - expect(user.id).toBe('uid3'); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(true); expect(user.existed()).toBe(true); }); - it('can hydrate a user with sessionToken in non server environment', async () => { + it("can hydrate a user with sessionToken in non server environment", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); const user = await ParseUser.hydrate({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc', + objectId: "uid3", + username: "username", + sessionToken: "123abc", }); - expect(user.id).toBe('uid3'); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it('can hydrate a user without sessionToken', async () => { + it("can hydrate a user without sessionToken", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); await ParseUser.logOut(); const user = await ParseUser.hydrate({ - objectId: 'uid3', - username: 'username', + objectId: "uid3", + username: "username", }); - expect(user.id).toBe('uid3'); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it('can send a password reset request', () => { + it("can send a password reset request", () => { CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('POST'); - expect(path).toBe('requestPasswordReset'); - expect(body).toEqual({ email: 'me@parse.com' }); + expect(method).toBe("POST"); + expect(path).toBe("requestPasswordReset"); + expect(body).toEqual({ email: "me@parse.com" }); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); - ParseUser.requestPasswordReset('me@parse.com'); + ParseUser.requestPasswordReset("me@parse.com"); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('POST'); - expect(path).toBe('requestPasswordReset'); - expect(body).toEqual({ email: 'me@parse.com' }); + expect(method).toBe("POST"); + expect(path).toBe("requestPasswordReset"); + expect(body).toEqual({ email: "me@parse.com" }); expect(options.useMasterKey).toBe(true); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); - ParseUser.requestPasswordReset('me@parse.com', { useMasterKey: true }); + 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 - })); + const path = Storage.generatePath("currentUser"); + 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'); - expect(u.getSessionToken()).toBe('12345'); + expect(u.getUsername()).toBe("bob"); + expect(u.id).toBe("abc"); + expect(u.getSessionToken()).toBe("12345"); ParseUser._clearCache(); const user = ParseUser.current(); expect(user instanceof ParseUser).toBe(true); - expect(user.getUsername()).toBe('bob'); - expect(user.id).toBe('abc'); - expect(user.getSessionToken()).toBe('12345'); + expect(user.getUsername()).toBe("bob"); + expect(user.id).toBe("abc"); + expect(user.getSessionToken()).toBe("12345"); done(); }); }); - 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 - })); + const path = Storage.generatePath("currentUser"); + 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'); - expect(u.getSessionToken()).toBe('12345'); + expect(u.getUsername()).toBe("bob"); + expect(u.id).toBe("abc"); + expect(u.getSessionToken()).toBe("12345"); ParseUser._clearCache(); const user = ParseUser.current(); expect(user instanceof ParseUser).toBe(true); - expect(user.getUsername()).toBe('bob'); - expect(user.id).toBe('abc'); - expect(user.getSessionToken()).toBe('12345'); + expect(user.getUsername()).toBe("bob"); + expect(user.id).toBe("abc"); + expect(user.getSessionToken()).toBe("12345"); done(); }); }); - 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 () => { + it("updates the current user on disk when fetched with include", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: "uid6", + }, + 200 + ); }, ajax() {}, }); - const child = new ParseObject('TestObject'); - child.set('foo', 'bar'); + const child = new ParseObject("TestObject"); + child.set("foo", "bar"); await child.save(); - let u = await ParseUser.signUp('spot', 'fetchWithInclude'); + let u = await ParseUser.signUp("spot", "fetchWithInclude"); expect(u.isCurrent()).toBe(true); ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - child: child.toJSON(), - count: 15, - }, 200); + return Promise.resolve( + { + child: child.toJSON(), + count: 15, + }, + 200 + ); }, ajax() {}, }); - u = await u.fetchWithInclude('child'); + u = await u.fetchWithInclude("child"); ParseUser._clearCache(); ParseObject._clearAllState(); expect(u.attributes).toEqual({}); - expect(u.get('count')).toBe(undefined); + expect(u.get("count")).toBe(undefined); const current = await ParseUser.currentAsync(); - expect(current.id).toBe('uid6'); - expect(current.get('count')).toBe(15); - expect(current.get('child').foo).toBe('bar'); + expect(current.id).toBe("uid6"); + expect(current.get("count")).toBe(15); + expect(current.get("child").foo).toBe("bar"); }); - it('does not update non-auth user when fetched with include', async () => { + it("does not update non-auth user when fetched with include", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: "uid6", + }, + 200 + ); }, ajax() {}, }); - const child = new ParseObject('TestObject'); - child.set('foo', 'bar'); + const child = new ParseObject("TestObject"); + child.set("foo", "bar"); await child.save(); - const u = await ParseUser.signUp('spot', 'fetchWithInclude'); + const u = await ParseUser.signUp("spot", "fetchWithInclude"); await ParseUser.logOut(); expect(u.isCurrent()).toBe(false); ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - child: child.toJSON(), - count: 15, - }, 200); + return Promise.resolve( + { + child: child.toJSON(), + count: 15, + }, + 200 + ); }, ajax() {}, }); - const fetchedUser = await u.fetchWithInclude('child'); + const fetchedUser = await u.fetchWithInclude("child"); const current = await ParseUser.currentAsync(); expect(current).toBe(null); - expect(fetchedUser.get('count')).toBe(15); - expect(fetchedUser.get('child').foo).toBe('bar'); + expect(fetchedUser.get("count")).toBe(15); + 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() {} + 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() {}, + }); + 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 () => { + it("can retreive a user with sessionToken (me)", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('users/me'); - expect(options.sessionToken).toBe('123abc'); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("users/me"); + expect(options.sessionToken).toBe("123abc"); + return Promise.resolve( + { + objectId: "uid3", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - const user = await ParseUser.me('123abc'); - expect(user.id).toBe('uid3'); + const user = await ParseUser.me("123abc"); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it('can retreive a user with sessionToken and masterKey(me)', async () => { + it("can retreive a user with sessionToken and masterKey(me)", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('GET'); - expect(path).toBe('users/me'); - expect(options.sessionToken).toBe('123abc'); + expect(method).toBe("GET"); + 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 }); - expect(user.id).toBe('uid3'); + const user = await ParseUser.me("123abc", { useMasterKey: true }); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it('can logout user with sessionToken', async () => { + it("can logout user with sessionToken", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); @@ -904,39 +1005,44 @@ describe('ParseUser', () => { request() { return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }; - jest.spyOn(RESTController, 'request'); + jest.spyOn(RESTController, "request"); CoreManager.setRESTController(RESTController); - await ParseUser.logOut({ sessionToken: '1234' }); + 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(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, - 'Another user is already linked to this facebook id.' + "Another user is already linked to this facebook id." ); return Promise.reject(error); }, - ajax() {} + ajax() {}, }); const provider = { authenticate(options) { if (options.success) { options.success(this, { - id: 'id', - access_token: 'access_token' + id: "id", + access_token: "access_token", }); } }, @@ -944,32 +1050,37 @@ describe('ParseUser', () => { restoreAuthentication() {}, getAuthType() { - return 'test'; + 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 () => { + it("can sync anonymous user with current user", async () => { const provider = AnonymousUtils._getAuthProvider(); - jest.spyOn(provider, 'restoreAuthentication'); + jest.spyOn(provider, "restoreAuthentication"); const object = new ParseUser(); - object.set('authData', provider.getAuthData()); + 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); @@ -981,49 +1092,57 @@ describe('ParseUser', () => { spy.mockRestore(); }); - it('can destroy anonymous user on logout', async () => { + it("can destroy anonymous user on logout", async () => { ParseUser.enableUnsafeCurrentUser(); 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'); + jest.spyOn(user, "destroy"); ParseUser._setCurrentUserCache(user); await ParseUser.logOut(); expect(user.destroy).toHaveBeenCalledTimes(1); }); - it('can unlink', async () => { + it("can unlink", async () => { const provider = AnonymousUtils._getAuthProvider(); ParseUser._registerAuthenticationProvider(provider); const user = new ParseUser(); - jest.spyOn(user, 'linkWith'); + jest.spyOn(user, "linkWith"); user._unlinkFrom(provider); expect(user.linkWith).toHaveBeenCalledTimes(1); - expect(user.linkWith).toHaveBeenCalledWith(provider, { authData: null }, undefined); + expect(user.linkWith).toHaveBeenCalledWith( + provider, + { authData: null }, + undefined + ); }); - it('can unlink with options', async () => { + it("can unlink with options", async () => { const provider = AnonymousUtils._getAuthProvider(); ParseUser._registerAuthenticationProvider(provider); const user = new ParseUser(); - jest.spyOn(user, 'linkWith') + jest + .spyOn(user, "linkWith") .mockImplementationOnce((authProvider, authData, saveOptions) => { expect(authProvider).toEqual(provider.getAuthType()); - expect(authData).toEqual({ authData: null}); + expect(authData).toEqual({ authData: null }); expect(saveOptions).toEqual({ useMasterKey: true }); return Promise.resolve(); }); @@ -1031,145 +1150,164 @@ describe('ParseUser', () => { expect(user.linkWith).toHaveBeenCalledTimes(1); }); - it('can destroy anonymous user when login new user', async () => { + it("can destroy anonymous user when login new user", async () => { ParseUser.enableUnsafeCurrentUser(); 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'); + jest.spyOn(user, "destroy"); ParseUser._setCurrentUserCache(user); 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', () => { + it("strip anonymity when we set username", () => { const user = new ParseUser(); const authData = { - anonymous : { - id : 'anonymousId' - } - } - user.set('authData', authData); - expect(user.get('authData').anonymous.id).toBe('anonymousId'); + anonymous: { + id: "anonymousId", + }, + }; + user.set("authData", authData); + expect(user.get("authData").anonymous.id).toBe("anonymousId"); // Set username should strip anonymous authData - user.setUsername('test'); - expect(user.getUsername()).toBe('test'); - expect(user.get('authData').anonymous).toBe(null); + user.setUsername("test"); + expect(user.getUsername()).toBe("test"); + 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) => { - expect(u.getSessionToken()).toBe('abc141'); - expect(u.get('number')).toBe(123); + 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); - expect(u.getSessionToken()).toBe('abc141'); - expect(u2.getSessionToken()).toBe('abc141'); - expect(u.get('number')).toBe(undefined); - expect(u2.get('number')).toBe(undefined); + 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); + expect(u2.get("number")).toBe(undefined); done(); }); }); - it('can linkWith options', async () => { + it("can linkWith options", async () => { ParseUser._clearCache(); 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); + expect(options).toEqual( + expect.objectContaining({ useMasterKey: true }) + ); + 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' + id: "id", + access_token: "access_token", }); } }, restoreAuthentication() {}, getAuthType() { - return 'test'; + 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 () => { + it("handle linkWith authentication failure", async () => { const provider = { authenticate(options) { if (options.error) { options.error(this, { - message: 'authentication failed', + message: "authentication failed", }); } }, restoreAuthentication() {}, getAuthType() { - return 'test'; + return "test"; }, - deauthenticate() {} + deauthenticate() {}, }; const user = new ParseUser(); @@ -1177,50 +1315,55 @@ 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"); } }); - it('can linkWith if no provider', async () => { + it("can linkWith if no provider", async () => { 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' } }); - expect(user.get('authData')).toEqual({ testProvider: { id: 'test' } }); + await user._linkWith("testProvider", { authData: { id: "test" } }); + expect(user.get("authData")).toEqual({ testProvider: { id: "test" } }); - jest.spyOn(user, 'linkWith'); + jest.spyOn(user, "linkWith"); - await user._unlinkFrom('testProvider'); + await user._unlinkFrom("testProvider"); const authProvider = user.linkWith.mock.calls[0][0]; - expect(authProvider).toBe('testProvider'); + expect(authProvider).toBe("testProvider"); }); - it('cannot linkWith invalid authData', async () => { + it("cannot linkWith invalid authData", async () => { ParseUser._clearCache(); const user = new ParseUser(); - user.set('authData', 1234); + user.set("authData", 1234); try { - await user.linkWith('testProvider', { authData: { id: 'test' } }); + await user.linkWith("testProvider", { authData: { id: "test" } }); expect(false).toBe(true); } catch (e) { - expect(e.message).toBe('Invalid type: authData field should be an object'); + expect(e.message).toBe( + "Invalid type: authData field should be an object" + ); } }); - it('_synchronizeAuthData can unlink on failure to restore auth ', async () => { + it("_synchronizeAuthData can unlink on failure to restore auth ", async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1229,53 +1372,53 @@ describe('ParseUser', () => { return false; }, getAuthType() { - return 'test'; + return "test"; }, }; const user = new ParseUser(); - user.id = 'sync123'; - user.set('authData', { test: true }); + user.id = "sync123"; + user.set("authData", { test: true }); ParseUser._setCurrentUserCache(user); - jest.spyOn(user, '_unlinkFrom'); + jest.spyOn(user, "_unlinkFrom"); user._synchronizeAuthData(provider); expect(user._unlinkFrom).toHaveBeenCalledTimes(1); }); - it('_isLinked', () => { + it("_isLinked", () => { const user = new ParseUser(); const provider = { - getAuthType: () => 'customAuth', + getAuthType: () => "customAuth", }; - user.set('authData', { 'customAuth': true }); + user.set("authData", { customAuth: true }); expect(user._isLinked(provider)).toBe(true); - user.set('authData', 1234); + user.set("authData", 1234); expect(user._isLinked(provider)).toBe(false); }); - it('_cleanupAuthData', () => { + it("_cleanupAuthData", () => { ParseUser.enableUnsafeCurrentUser(); const user = new ParseUser(); - user.id = 'cleanupData1'; - user.set('authData', { toRemove: null, test: true }); + user.id = "cleanupData1"; + user.set("authData", { toRemove: null, test: true }); user._cleanupAuthData(); - expect(user.get('authData')).toEqual({ toRemove: null, test: true }); + expect(user.get("authData")).toEqual({ toRemove: null, test: true }); ParseUser._setCurrentUserCache(user); user._cleanupAuthData(); - expect(user.get('authData')).toEqual({ test: true }); + expect(user.get("authData")).toEqual({ test: true }); - user.set('authData', 1234); + user.set("authData", 1234); user._cleanupAuthData(); - expect(user.get('authData')).toEqual(1234); + expect(user.get("authData")).toEqual(1234); }); - it('_logOutWith', () => { + it("_logOutWith", () => { const user = new ParseUser(); - user.id = 'logout1234'; + user.id = "logout1234"; const provider = { deauthenticate: jest.fn(), }; @@ -1287,47 +1430,54 @@ describe('ParseUser', () => { expect(provider.deauthenticate).toHaveBeenCalledTimes(1); }); - it('_logInWith', async () => { + it("_logInWith", async () => { ParseUser.disableUnsafeCurrentUser(); 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' + id: "id", + access_token: "access_token", }); } }, restoreAuthentication() {}, getAuthType() { - return 'test'; + 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 () => { - CoreManager.set('ENCRYPTED_USER', true); - CoreManager.set('ENCRYPTED_KEY', 'hello'); + it("can encrypt user", async () => { + CoreManager.set("ENCRYPTED_USER", true); + CoreManager.set("ENCRYPTED_KEY", "hello"); ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1335,51 +1485,54 @@ describe('ParseUser', () => { let u = null; CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('GET'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("login"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + return Promise.resolve( + { + objectId: "uid2", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - u = await ParseUser.logIn('username', 'password'); + u = await ParseUser.logIn("username", "password"); // Clear cache to read from disk ParseUser._clearCache(); - expect(u.id).toBe('uid2'); - expect(u.getSessionToken()).toBe('123abc'); + expect(u.id).toBe("uid2"); + expect(u.getSessionToken()).toBe("123abc"); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); const currentUser = ParseUser.current(); - expect(currentUser.id).toBe('uid2'); + expect(currentUser.id).toBe("uid2"); ParseUser._clearCache(); const currentUserAsync = await ParseUser.currentAsync(); - expect(currentUserAsync.id).toEqual('uid2'); + expect(currentUserAsync.id).toEqual("uid2"); - const path = Storage.generatePath('currentUser'); + const path = Storage.generatePath("currentUser"); const encryptedUser = Storage.getItem(path); const crypto = CoreManager.getCryptoController(); - const decryptedUser = crypto.decrypt(encryptedUser, 'hello'); + const decryptedUser = crypto.decrypt(encryptedUser, "hello"); expect(JSON.parse(decryptedUser).objectId).toBe(u.id); - CoreManager.set('ENCRYPTED_USER', false); - CoreManager.set('ENCRYPTED_KEY', null); + CoreManager.set("ENCRYPTED_USER", false); + CoreManager.set("ENCRYPTED_KEY", null); Storage._clear(); }); - it('can encrypt user with custom CryptoController', async () => { - CoreManager.set('ENCRYPTED_USER', true); - CoreManager.set('ENCRYPTED_KEY', 'hello'); - const ENCRYPTED_DATA = 'encryptedString'; + it("can encrypt user with custom CryptoController", async () => { + CoreManager.set("ENCRYPTED_USER", true); + CoreManager.set("ENCRYPTED_KEY", "hello"); + const ENCRYPTED_DATA = "encryptedString"; ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1387,244 +1540,270 @@ describe('ParseUser', () => { let u = null; CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('GET'); - expect(path).toBe('login'); - expect(body.username).toBe('username'); - expect(body.password).toBe('password'); - - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(method).toBe("GET"); + expect(path).toBe("login"); + expect(body.username).toBe("username"); + expect(body.password).toBe("password"); + + return Promise.resolve( + { + objectId: "uid2", + username: "username", + sessionToken: "123abc", + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const CustomCrypto = { encrypt(obj, secretKey) { - expect(secretKey).toBe('hello'); + expect(secretKey).toBe("hello"); return ENCRYPTED_DATA; }, decrypt(encryptedText, secretKey) { expect(encryptedText).toBe(ENCRYPTED_DATA); - expect(secretKey).toBe('hello'); + expect(secretKey).toBe("hello"); return JSON.stringify(u.toJSON()); }, }; CoreManager.setCryptoController(CustomCrypto); - u = await ParseUser.logIn('username', 'password'); + u = await ParseUser.logIn("username", "password"); // Clear cache to read from disk ParseUser._clearCache(); - expect(u.id).toBe('uid2'); - expect(u.getSessionToken()).toBe('123abc'); + expect(u.id).toBe("uid2"); + expect(u.getSessionToken()).toBe("123abc"); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); - expect(ParseUser.current().id).toBe('uid2'); + expect(ParseUser.current().id).toBe("uid2"); - const path = Storage.generatePath('currentUser'); + const path = Storage.generatePath("currentUser"); const userStorage = Storage.getItem(path); expect(userStorage).toBe(ENCRYPTED_DATA); - CoreManager.set('ENCRYPTED_USER', false); - CoreManager.set('ENCRYPTED_KEY', null); + CoreManager.set("ENCRYPTED_USER", false); + CoreManager.set("ENCRYPTED_KEY", null); Storage._clear(); }); - it('can static signup a user with installationId', async () => { + it("can static signup a user with installationId", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); - const installationId = '12345678'; + const installationId = "12345678"; CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('POST'); - expect(path).toBe('users'); + expect(method).toBe("POST"); + 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 }); - expect(user.id).toBe('uid3'); + 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); }); - it('can signup a user with installationId', async () => { + it("can signup a user with installationId", async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); - const installationId = '12345678'; + const installationId = "12345678"; CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('POST'); - expect(path).toBe('users'); + 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(); - user.setUsername('name'); - user.setPassword('pass'); + user.setUsername("name"); + user.setPassword("pass"); await user.signUp(null, { installationId }); - expect(user.id).toBe('uid3'); + expect(user.id).toBe("uid3"); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it('can verify user password', async () => { + it("can verify user password", async () => { ParseUser.enableUnsafeCurrentUser(); 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'); - expect(user.username).toBe('username'); + const user = await ParseUser.verifyPassword("username", "password"); + expect(user.objectId).toBe("uid2"); + expect(user.username).toBe("username"); const notStatic = new ParseUser(); - notStatic.setUsername('username'); - const userAgain = await notStatic.verifyPassword('password', { useMasterKey: true }); - expect(userAgain.objectId).toBe('uid2'); - expect(userAgain.username).toBe('username'); + notStatic.setUsername("username"); + const userAgain = await notStatic.verifyPassword("password", { + useMasterKey: true, + }); + expect(userAgain.objectId).toBe("uid2"); + expect(userAgain.username).toBe("username"); CoreManager.setRESTController({ request() { const parseError = new ParseError( ParseError.OBJECT_NOT_FOUND, - 'Invalid username/password.' + "Invalid username/password." ); 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.'); + expect(error.message).toBe("Invalid username/password."); } try { - await ParseUser.verifyPassword(null, 'password'); - } catch(error) { + await ParseUser.verifyPassword(null, "password"); + } catch (error) { expect(error.code).toBe(-1); - expect(error.message).toBe('Username must be a string.'); + expect(error.message).toBe("Username must be a string."); } try { - await ParseUser.verifyPassword('username', null); - } catch(error) { + await ParseUser.verifyPassword("username", null); + } catch (error) { expect(error.code).toBe(-1); - expect(error.message).toBe('Password must be a string.'); + expect(error.message).toBe("Password must be a string."); } }); - it('can send an email verification request', () => { + it("can send an email verification request", () => { CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('POST'); + expect(method).toBe("POST"); expect(path).toBe("verificationEmailRequest"); expect(body).toEqual({ email: "me@parse.com" }); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); ParseUser.requestEmailVerification("me@parse.com"); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe('POST'); + expect(method).toBe("POST"); 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 }); }); - it('allowCustomUserClass', () => { - expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(true); + it("allowCustomUserClass", () => { + expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(true); ParseUser.allowCustomUserClass(true); - expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(false); + expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(false); ParseUser.allowCustomUserClass(false); - expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(true); + expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(true); }); - it('enableRevocableSession', async () => { + it("enableRevocableSession", async () => { const result = await ParseUser.enableRevocableSession(); - expect(CoreManager.get('FORCE_REVOCABLE_SESSION')).toBe(true); + expect(CoreManager.get("FORCE_REVOCABLE_SESSION")).toBe(true); expect(result).toBeUndefined(); ParseUser.enableUnsafeCurrentUser(); 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'); + const user = await ParseUser.logIn("username", "password"); + jest.spyOn(user, "_upgradeToRevocableSession"); await ParseUser.enableRevocableSession({ useMasterKey: true }); expect(user._upgradeToRevocableSession).toHaveBeenCalled(); }); - it('upgradeToRevocableSession', async () => { + it("upgradeToRevocableSession", async () => { try { const unsavedUser = new ParseUser(); await unsavedUser._upgradeToRevocableSession(); } catch (e) { - expect(e.message).toBe('Cannot upgrade a user with no session token'); + expect(e.message).toBe("Cannot upgrade a user with no session token"); } ParseUser.disableUnsafeCurrentUser(); 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 user = await ParseUser.logIn("username", "password"); const upgradedUser = await user._upgradeToRevocableSession(); expect(user).toEqual(upgradedUser); }); - it('extend', () => { + it("extend", () => { 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..91c954d24 100644 --- a/src/__tests__/Push-test.js +++ b/src/__tests__/Push-test.js @@ -7,115 +7,120 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../CoreManager'); -jest.dontMock('../Push'); -jest.dontMock('./test_helpers/asyncHelper'); +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); +jest.setMock("../ParseQuery", mockQuery); -const CoreManager = require('../CoreManager'); -const ParseQuery = require('../ParseQuery'); -const Push = require('../Push'); +const CoreManager = require("../CoreManager"); +const ParseQuery = require("../ParseQuery"); +const Push = require("../Push"); const defaultController = CoreManager.getPushController(); -describe('Push', () => { +describe("Push", () => { beforeEach(() => { CoreManager.setPushController({ 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 + 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)) + push_time: new Date(Date.UTC(2015, 1, 1)), }).then((data) => { - expect(data.push_time).toBe('2015-02-01T00:00:00.000Z'); + 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' + push_time: "2015-02-01T00:00:00.000", }).then((data) => { - expect(data.push_time).toBe('2015-02-01T00:00:00.000'); + 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)) + expiration_time: new Date(Date.UTC(2015, 1, 1)), }).then((data) => { - expect(data.expiration_time).toBe('2015-02-01T00:00:00.000Z'); + 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.'); + 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."); }); }); -describe('PushController', () => { - it('forwards data along', () => { +describe("PushController", () => { + it("forwards data along", () => { CoreManager.setPushController(defaultController); 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} + "POST", + "push", + { push_time: "2015-02-01T00:00:00.000Z" }, + { useMasterKey: true }, ]); }); }); diff --git a/src/__tests__/RESTController-test.js b/src/__tests__/RESTController-test.js index 80cdf1040..62917ba6c 100644 --- a/src/__tests__/RESTController-test.js +++ b/src/__tests__/RESTController-test.js @@ -9,71 +9,83 @@ jest.autoMockOff(); jest.useFakeTimers(); -jest.mock('uuid/v4', () => { +jest.mock("uuid/v4", () => { let value = 1000; return () => (value++).toString(); }); -const CoreManager = require('../CoreManager'); -const RESTController = require('../RESTController'); -const mockXHR = require('./test_helpers/mockXHR'); -const mockWeChat = require('./test_helpers/mockWeChat'); +const CoreManager = require("../CoreManager"); +const RESTController = require("../RESTController"); +const mockXHR = require("./test_helpers/mockXHR"); +const mockWeChat = require("./test_helpers/mockWeChat"); global.wx = mockWeChat; CoreManager.setInstallationController({ currentInstallationId() { - return Promise.resolve('iid'); - } + return Promise.resolve("iid"); + }, }); -CoreManager.set('APPLICATION_ID', 'A'); -CoreManager.set('JAVASCRIPT_KEY', 'B'); -CoreManager.set('VERSION', 'V'); +CoreManager.set("APPLICATION_ID", "A"); +CoreManager.set("JAVASCRIPT_KEY", "B"); +CoreManager.set("VERSION", "V"); function flushPromises() { - return new Promise(resolve => setImmediate(resolve)); + return new Promise((resolve) => setImmediate(resolve)); } -describe('RESTController', () => { - it('throws if there is no XHR implementation', () => { +describe("RESTController", () => { + it("throws if there is no XHR implementation", () => { RESTController._setXHR(null); expect(RESTController._getXHR()).toBe(null); - expect(RESTController.ajax.bind(null, 'GET', 'users/me', {})).toThrow( - 'Cannot make a request: No definition of XMLHttpRequest was found.' + expect(RESTController.ajax.bind(null, "GET", "users/me", {})).toThrow( + "Cannot make a request: No definition of XMLHttpRequest was found." ); }); - it('opens a XHR with the correct verb and headers', () => { + it("opens a XHR with the correct verb and headers", () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - 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' ] + RESTController._setXHR(function () { + return xhr; + }); + RESTController.ajax( + "GET", + "users/me", + {}, + { "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 }}])); - RESTController.ajax('POST', 'users', {}).then(({ response, status }) => { + 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); done(); }); }); - 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 }) => { + 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); done(); @@ -81,48 +93,61 @@ 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) => { - expect(err).toBe('Unable to connect to the Parse API'); + 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) => { + 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"'); + 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(); }); @@ -130,218 +155,269 @@ describe('RESTController', () => { 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(); }); jest.runAllTimers(); }); - it('can make formal JSON requests', async () => { + it("can make formal JSON requests", async () => { 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' }); - 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" } ); + 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', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: 'iid', - _SessionToken: '1234', + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "iid", + _SessionToken: "1234", }); }); - it('handles request errors', (done) => { - RESTController._setXHR(mockXHR([{ - status: 400, response: { - code: -1, - error: 'Something bad' - } - }])); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { + 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'); + 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.responseText = "{"; this.readyState = 4; this.onreadystatechange(); - } + }, }; RESTController._setXHR(XHR); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { + RESTController.request("GET", "classes/MyObject", {}, {}).then( + null, + (error) => { expect(error.code).toBe(100); - expect(error.message.indexOf('XMLHttpRequest failed')).toBe(0); + 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.responseText = "{"; this.readyState = 4; this.onreadystatechange(); - } + }, }; RESTController._setXHR(XHR); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { + 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: {'); + 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() { }; + it("handles x-parse-job-status-id header", async () => { + 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.responseText = "{}"; this.readyState = 4; this.onreadystatechange(); }, - getAllResponseHeaders: function() { - return 'x-parse-job-status-id: 1234'; - } + 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() { }; + it("handles invalid header", async () => { + 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', {}, {}) - expect(response.result).toBe('hello'); + 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]; + it("idempotency - sends requestId header", async () => { + CoreManager.set("IDEMPOTENCY", true); + 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.request('POST', 'classes/MyObject', {}, {}); + 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', {}, {}); + RESTController.request("PUT", "classes/MyObject", {}, {}); await flushPromises(); - expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual( - [["X-Parse-Request-Id", '1001']] - ); - CoreManager.set('IDEMPOTENCY', false); + 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) => { - CoreManager.set('IDEMPOTENCY', 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(); - expect(requestIdHeaders.length).toBe(3); - expect(response).toEqual({ success: true }); - expect(status).toBe(200); - 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.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(); + expect(requestIdHeaders.length).toBe(3); + expect(response).toEqual({ success: true }); + expect(status).toBe(200); + done(); + } + ); jest.runAllTimers(); - CoreManager.set('IDEMPOTENCY', false); + CoreManager.set("IDEMPOTENCY", false); }); - it('idempotency - should properly handle url method not POST / PUT', () => { - CoreManager.set('IDEMPOTENCY', true); + it("idempotency - should properly handle url method not POST / PUT", () => { + CoreManager.set("IDEMPOTENCY", true); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - RESTController.ajax('GET', 'users/me', {}, {}); - const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter((header) => 'X-Parse-Request-Id' === header[0]); + RESTController._setXHR(function () { + return xhr; + }); + RESTController.ajax("GET", "users/me", {}, {}); + const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter( + (header) => "X-Parse-Request-Id" === header[0] + ); expect(requestIdHeaders.length).toBe(0); - CoreManager.set('IDEMPOTENCY', false); + 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 () => { + it("attaches the session token of the current user", async () => { CoreManager.setUserController({ currentUserAsync() { - return Promise.resolve({ getSessionToken: () => '5678' }); + return Promise.resolve({ getSessionToken: () => "5678" }); }, setCurrentUser() {}, currentUser() {}, @@ -360,23 +436,25 @@ 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', {}, {}); + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request("GET", "classes/MyObject", {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: 'GET', - _ApplicationId: 'A', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: 'iid', - _SessionToken: '5678', - }); - CoreManager.set('UserController', undefined); // Clean up + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "iid", + _SessionToken: "5678", + }); + CoreManager.set("UserController", undefined); // Clean up }); - it('attaches no session token when there is no current user', async () => { + it("attaches no session token when there is no current user", async () => { CoreManager.setUserController({ currentUserAsync() { return Promise.resolve(null); @@ -398,230 +476,292 @@ 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', {}, {}); + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request("GET", "classes/MyObject", {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: 'GET', - _ApplicationId: 'A', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: 'iid', + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "iid", }); - CoreManager.set('UserController', undefined); // Clean up + CoreManager.set("UserController", undefined); // Clean up }); - it('sends the revocable session upgrade header when the config flag is set', async () => { - CoreManager.set('FORCE_REVOCABLE_SESSION', true); + it("sends the revocable session upgrade header when the config flag is set", async () => { + CoreManager.set("FORCE_REVOCABLE_SESSION", true); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - RESTController.request('GET', 'classes/MyObject', {}, {}); + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request("GET", "classes/MyObject", {}, {}); await flushPromises(); xhr.onreadystatechange(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: 'GET', - _ApplicationId: 'A', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: 'iid', - _RevocableSession: '1' - }); - CoreManager.set('FORCE_REVOCABLE_SESSION', false); // Clean up + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "iid", + _RevocableSession: "1", + }); + CoreManager.set("FORCE_REVOCABLE_SESSION", false); // Clean up }); - it('sends the master key when requested', async () => { - CoreManager.set('MASTER_KEY', 'M'); + it("sends the master key when requested", async () => { + CoreManager.set("MASTER_KEY", "M"); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - RESTController.request('GET', 'classes/MyObject', {}, { useMasterKey: true }); + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request( + "GET", + "classes/MyObject", + {}, + { useMasterKey: true } + ); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: 'GET', - _ApplicationId: 'A', - _MasterKey: 'M', - _ClientVersion: 'V', - _InstallationId: 'iid', + _method: "GET", + _ApplicationId: "A", + _MasterKey: "M", + _ClientVersion: "V", + _InstallationId: "iid", }); }); - it('includes the status code when requested', (done) => { - RESTController._setXHR(mockXHR([{ status: 200, response: { success: true }}])); - RESTController.request('POST', 'users', {}, { returnStatus: true }) - .then((response) => { + 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', () => { - CoreManager.set('MASTER_KEY', undefined); + it("throws when attempted to use an unprovided master key", () => { + CoreManager.set("MASTER_KEY", undefined); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - 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.' - ); + 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."); }); - 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'); + 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 xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - RESTController.request('GET', 'classes/MyObject', {}, {}); + 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"]] - ); - CoreManager.set('SERVER_AUTH_TYPE', null); - CoreManager.set('SERVER_AUTH_TOKEN', null); + 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(); - }); + 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(); + } + ); }); - 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(); - }); + 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(); + } + ); }); - it('opens a XHR with the custom headers', () => { - CoreManager.set('REQUEST_HEADERS', { 'Cache-Control' : 'max-age=3600' }); + it("opens a XHR with the custom headers", () => { + 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.ajax('GET', 'users/me', {}, { 'X-Parse-Session-Token': '123' }); - expect(xhr.setRequestHeader.mock.calls[3]).toEqual( - [ 'Cache-Control', 'max-age=3600' ] + RESTController._setXHR(function () { + return xhr; + }); + RESTController.ajax( + "GET", + "users/me", + {}, + { "X-Parse-Session-Token": "123" } ); - 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', {}); + CoreManager.set("REQUEST_HEADERS", {}); }); - it('can handle installationId option', async () => { + it("can handle installationId option", async () => { 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', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: '5678', - _SessionToken: '1234', + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "5678", + _SessionToken: "1234", }); }); - it('can handle wechat request', async () => { - const XHR = require('../Xhr.weapp'); + it("can handle wechat request", async () => { + const XHR = require("../Xhr.weapp"); 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] + 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, + ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: 'GET', - _ApplicationId: 'A', - _JavaScriptKey: 'B', - _ClientVersion: 'V', - _InstallationId: '5678', - _SessionToken: '1234', + _method: "GET", + _ApplicationId: "A", + _JavaScriptKey: "B", + _ClientVersion: "V", + _InstallationId: "5678", + _SessionToken: "1234", }); }); - it('can handle wechat ajax', async () => { - const XHR = require('../Xhr.weapp'); + it("can handle wechat ajax", async () => { + const XHR = require("../Xhr.weapp"); const xhr = new XHR(); - jest.spyOn(xhr, 'open'); - jest.spyOn(xhr, 'send'); - jest.spyOn(xhr, 'setRequestHeader'); - 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 ]); + jest.spyOn(xhr, "open"); + jest.spyOn(xhr, "send"); + jest.spyOn(xhr, "setRequestHeader"); + 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.send.mock.calls[0][0]).toEqual({}); xhr.responseHeader = headers; - expect(xhr.getAllResponseHeaders().includes('X-Parse-Session-Token')).toBe(true); - expect(xhr.getResponseHeader('X-Parse-Session-Token')).toBe('123'); + expect(xhr.getAllResponseHeaders().includes("X-Parse-Session-Token")).toBe( + true + ); + expect(xhr.getResponseHeader("X-Parse-Session-Token")).toBe("123"); xhr.abort(); xhr.abort(); }); diff --git a/src/__tests__/SingleInstanceStateController-test.js b/src/__tests__/SingleInstanceStateController-test.js index 4bad43381..3c1021bc1 100644 --- a/src/__tests__/SingleInstanceStateController-test.js +++ b/src/__tests__/SingleInstanceStateController-test.js @@ -7,401 +7,760 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseOp'); -jest.dontMock('../promiseUtils'); -jest.dontMock('../SingleInstanceStateController'); -jest.dontMock('../TaskQueue'); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseOp"); +jest.dontMock("../promiseUtils"); +jest.dontMock("../SingleInstanceStateController"); +jest.dontMock("../TaskQueue"); -const mockObject = function() {}; -mockObject.registerSubclass = function() {}; -jest.setMock('../ParseObject', mockObject); +const mockObject = function () {}; +mockObject.registerSubclass = function () {}; +jest.setMock("../ParseObject", mockObject); jest.useFakeTimers(); -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParseOps = require('../ParseOp'); -const SingleInstanceStateController = require('../SingleInstanceStateController'); -const TaskQueue = require('../TaskQueue'); +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseOps = require("../ParseOp"); +const SingleInstanceStateController = require("../SingleInstanceStateController"); +const TaskQueue = require("../TaskQueue"); -describe('SingleInstanceStateController', () => { - it('returns null state for an unknown object', () => { - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'someId' })).toBe(null); +describe("SingleInstanceStateController", () => { + it("returns null state for an unknown object", () => { + 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({}); + it("returns empty data for an unknown object", () => { + 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([{}]); + it("returns an empty op queue for an unknown object", () => { + 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({ + 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({ 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({ + it("can clear all data", () => { + 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); + it("initializes server data when setting pending ops", () => { + 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "B" }, + "counter", + op + ); + 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({ + 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({ 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({ + it("can remove server data from a state", () => { + 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, }); }); - it('can add multiple pending Ops', () => { + it("can add multiple pending Ops", () => { const op = new ParseOps.IncrementOp(1); 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "E" }, + "counter", + op + ); + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "E" }, + "valid", + op2 + ); + 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "E" }, + "valid", + op3 + ); + 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', () => { + 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "F" }, + "counter", + op + ); + 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', () => { + 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "G" }, + "counter", + op + ); + 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", }); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'G' }); - 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, }); const op2 = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'G' }, 'valid', op2); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'G' })).toEqual({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "G" }, + "valid", + op2 + ); + 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', () => { + 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.setPendingOp( + { className: "someClass", id: "H" }, + "counter", + op + ); + 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({ + it("will never leave the pending Op queue empty", () => { + 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' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'I' })).toEqual({ + SingleInstanceStateController.popPendingState({ + className: "someClass", + id: "I", + }); + 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); + 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); 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' }); + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "J" }, + "counter", + op + ); + 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); + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "J" }, + "counter", + op2 + ); + 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 }); + it("can estimate all attributes", () => { + 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({ + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "K" }, + "counter", + op + ); + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "K" }, + "valid", + op2 + ); + 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 + SingleInstanceStateController.setPendingOp( + { className: "someClass", id: "K" }, + "valid", + op3 + ); + 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({ + 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({ counter: 12, - valid: true + valid: true, }); }); - it('can enqueue a chain of tasks', async () => { + 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 called = [false, false, false]; - SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { - return p1.then(() => { - called[0] = true; - }); + const p1 = new Promise((resolve) => { + p1Resolve = resolve; }); - SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { - return p2.then(() => { - called[1] = true; - }); - }); - SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { - called[2] = true; - return Promise.resolve(); + const p2 = new Promise((resolve) => { + p2Resolve = resolve; }); + const called = [false, false, false]; + SingleInstanceStateController.enqueueTask( + { className: "someClass", id: "M" }, + () => { + return p1.then(() => { + called[0] = true; + }); + } + ); + SingleInstanceStateController.enqueueTask( + { className: "someClass", id: "M" }, + () => { + return p2.then(() => { + called[1] = true; + }); + } + ); + SingleInstanceStateController.enqueueTask( + { className: "someClass", id: "M" }, + () => { + called[2] = true; + return Promise.resolve(); + } + ); expect(called).toEqual([false, false, false]); p1Resolve(); await p1; expect(called).toEqual([true, false, false]); p2Resolve(); await p2; - await new Promise(resolve => setImmediate(resolve)); + await new Promise((resolve) => setImmediate(resolve)); expect(called).toEqual([true, true, true]); }); - it('can merge the first entry into the next', () => { + 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' }); + 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", + }); 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' }); + it("stores cached versions of object attributes", () => { + 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', + __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({ + 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({ 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' }); + it("can duplicate the state of an object", () => { + const obj = { className: "someClass", id: "someId" }; + SingleInstanceStateController.setServerData(obj, { + counter: 12, + name: "original", + }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp(obj, 'counter', setCount); - SingleInstanceStateController.setPendingOp(obj, 'valid', setValid); + SingleInstanceStateController.setPendingOp(obj, "counter", setCount); + SingleInstanceStateController.setPendingOp(obj, "valid", setValid); - const duplicate = { className: 'someClass', id: 'dupId' }; + const duplicate = { className: "someClass", id: "dupId" }; SingleInstanceStateController.duplicateState(obj, duplicate); expect(SingleInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: 'original' }, + serverData: { counter: 12, name: "original" }, 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..068890787 100644 --- a/src/__tests__/Storage-test.js +++ b/src/__tests__/Storage-test.js @@ -9,9 +9,9 @@ jest.autoMockOff(); -const mockRNStorageInterface = require('./test_helpers/mockRNStorage'); -const mockWeChat = require('./test_helpers/mockWeChat'); -const CoreManager = require('../CoreManager'); +const mockRNStorageInterface = require("./test_helpers/mockRNStorage"); +const mockWeChat = require("./test_helpers/mockWeChat"); +const CoreManager = require("../CoreManager"); global.wx = mockWeChat; @@ -43,252 +43,267 @@ const mockStorageInterface = { clear() { mockStorage = {}; - } -} + }, +}; global.localStorage = mockStorageInterface; -const BrowserStorageController = require('../StorageController.browser'); +const BrowserStorageController = require("../StorageController.browser"); -describe('Browser StorageController', () => { +describe("Browser StorageController", () => { beforeEach(() => { BrowserStorageController.clear(); }); - it('is synchronous', () => { + it("is synchronous", () => { expect(BrowserStorageController.async).toBe(0); - expect(typeof BrowserStorageController.getItem).toBe('function'); - expect(typeof BrowserStorageController.setItem).toBe('function'); - expect(typeof BrowserStorageController.removeItem).toBe('function'); + expect(typeof BrowserStorageController.getItem).toBe("function"); + expect(typeof BrowserStorageController.setItem).toBe("function"); + expect(typeof BrowserStorageController.removeItem).toBe("function"); }); - it('can store and retrieve values', () => { - expect(BrowserStorageController.getItem('myKey')).toBe(null); - BrowserStorageController.setItem('myKey', 'myValue'); - expect(BrowserStorageController.getItem('myKey')).toBe('myValue'); + it("can store and retrieve values", () => { + expect(BrowserStorageController.getItem("myKey")).toBe(null); + BrowserStorageController.setItem("myKey", "myValue"); + expect(BrowserStorageController.getItem("myKey")).toBe("myValue"); }); - it('can remove values', () => { - BrowserStorageController.setItem('myKey', 'myValue'); - expect(BrowserStorageController.getItem('myKey')).toBe('myValue'); - BrowserStorageController.removeItem('myKey'); - expect(BrowserStorageController.getItem('myKey')).toBe(null); + it("can remove values", () => { + BrowserStorageController.setItem("myKey", "myValue"); + expect(BrowserStorageController.getItem("myKey")).toBe("myValue"); + BrowserStorageController.removeItem("myKey"); + expect(BrowserStorageController.getItem("myKey")).toBe(null); }); }); -const RNStorageController = require('../StorageController.react-native'); +const RNStorageController = require("../StorageController.react-native"); -describe('React Native StorageController', () => { +describe("React Native StorageController", () => { beforeEach(() => { CoreManager.setAsyncStorage(mockRNStorageInterface); RNStorageController.clear(); }); - it('is asynchronous', () => { + it("is asynchronous", () => { expect(RNStorageController.async).toBe(1); - expect(typeof RNStorageController.getItemAsync).toBe('function'); - expect(typeof RNStorageController.setItemAsync).toBe('function'); - expect(typeof RNStorageController.removeItemAsync).toBe('function'); + expect(typeof RNStorageController.getItemAsync).toBe("function"); + expect(typeof RNStorageController.setItemAsync).toBe("function"); + 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); + cb("Error Thrown", undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.setItemAsync('myKey', 'myValue').catch((error) => { - expect(error).toBe('Error Thrown'); + 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); + cb("Error Thrown", undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.getItemAsync('myKey').catch((error) => { - expect(error).toBe('Error Thrown'); + 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); + cb("Error Thrown", undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.removeItemAsync('myKey').catch((error) => { - expect(error).toBe('Error Thrown'); + 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); + cb("Error Thrown", undefined); }, }; CoreManager.setAsyncStorage(mockRNError); RNStorageController.getAllKeysAsync().catch((error) => { - expect(error).toBe('Error Thrown'); + expect(error).toBe("Error Thrown"); done(); }); }); }); -const DefaultStorageController = require('../StorageController.default'); +const DefaultStorageController = require("../StorageController.default"); -describe('Default StorageController', () => { +describe("Default StorageController", () => { beforeEach(() => { DefaultStorageController.clear(); }); - it('is synchronous', () => { + it("is synchronous", () => { expect(DefaultStorageController.async).toBe(0); - expect(typeof DefaultStorageController.getItem).toBe('function'); - expect(typeof DefaultStorageController.setItem).toBe('function'); - expect(typeof DefaultStorageController.removeItem).toBe('function'); + expect(typeof DefaultStorageController.getItem).toBe("function"); + expect(typeof DefaultStorageController.setItem).toBe("function"); + expect(typeof DefaultStorageController.removeItem).toBe("function"); }); - it('can store and retrieve values', () => { - expect(DefaultStorageController.getItem('myKey')).toBe(null); - DefaultStorageController.setItem('myKey', 'myValue'); - expect(DefaultStorageController.getItem('myKey')).toBe('myValue'); + it("can store and retrieve values", () => { + expect(DefaultStorageController.getItem("myKey")).toBe(null); + DefaultStorageController.setItem("myKey", "myValue"); + expect(DefaultStorageController.getItem("myKey")).toBe("myValue"); }); - it('can remove values', () => { - DefaultStorageController.setItem('myKey', 'myValue'); - expect(DefaultStorageController.getItem('myKey')).toBe('myValue'); - DefaultStorageController.removeItem('myKey'); - expect(DefaultStorageController.getItem('myKey')).toBe(null); + it("can remove values", () => { + DefaultStorageController.setItem("myKey", "myValue"); + expect(DefaultStorageController.getItem("myKey")).toBe("myValue"); + DefaultStorageController.removeItem("myKey"); + expect(DefaultStorageController.getItem("myKey")).toBe(null); }); }); -const WeappStorageController = require('../StorageController.weapp'); +const WeappStorageController = require("../StorageController.weapp"); -describe('WeChat StorageController', () => { +describe("WeChat StorageController", () => { beforeEach(() => { WeappStorageController.clear(); }); - it('is synchronous', () => { + it("is synchronous", () => { expect(WeappStorageController.async).toBe(0); - expect(typeof WeappStorageController.getItem).toBe('function'); - expect(typeof WeappStorageController.setItem).toBe('function'); - expect(typeof WeappStorageController.removeItem).toBe('function'); + expect(typeof WeappStorageController.getItem).toBe("function"); + expect(typeof WeappStorageController.setItem).toBe("function"); + expect(typeof WeappStorageController.removeItem).toBe("function"); }); - it('can store and retrieve values', () => { - expect(WeappStorageController.getItem('myKey')).toBe(undefined); - WeappStorageController.setItem('myKey', 'myValue'); - expect(WeappStorageController.getItem('myKey')).toBe('myValue'); - expect(WeappStorageController.getAllKeys()).toEqual(['myKey']); + it("can store and retrieve values", () => { + expect(WeappStorageController.getItem("myKey")).toBe(undefined); + WeappStorageController.setItem("myKey", "myValue"); + expect(WeappStorageController.getItem("myKey")).toBe("myValue"); + expect(WeappStorageController.getAllKeys()).toEqual(["myKey"]); }); - it('can remove values', () => { - WeappStorageController.setItem('myKey', 'myValue'); - expect(WeappStorageController.getItem('myKey')).toBe('myValue'); - WeappStorageController.removeItem('myKey'); - expect(WeappStorageController.getItem('myKey')).toBe(undefined); + it("can remove values", () => { + WeappStorageController.setItem("myKey", "myValue"); + expect(WeappStorageController.getItem("myKey")).toBe("myValue"); + WeappStorageController.removeItem("myKey"); + expect(WeappStorageController.getItem("myKey")).toBe(undefined); }); }); -const Storage = require('../Storage'); +const Storage = require("../Storage"); -describe('Storage (Default StorageController)', () => { +describe("Storage (Default StorageController)", () => { beforeEach(() => { - CoreManager.setStorageController(require('../StorageController.default')); + CoreManager.setStorageController(require("../StorageController.default")); }); - it('can store and retrieve values', () => { - expect(Storage.getItem('myKey')).toBe(null); - Storage.setItem('myKey', 'myValue'); - expect(Storage.getItem('myKey')).toBe('myValue'); - expect(Storage.getAllKeys()).toEqual(['myKey']); + it("can store and retrieve values", () => { + expect(Storage.getItem("myKey")).toBe(null); + Storage.setItem("myKey", "myValue"); + expect(Storage.getItem("myKey")).toBe("myValue"); + expect(Storage.getAllKeys()).toEqual(["myKey"]); }); - it('can remove values', () => { - Storage.setItem('myKey', 'myValue'); - expect(Storage.getItem('myKey')).toBe('myValue'); - Storage.removeItem('myKey'); - expect(Storage.getItem('myKey')).toBe(null); + it("can remove values", () => { + Storage.setItem("myKey", "myValue"); + expect(Storage.getItem("myKey")).toBe("myValue"); + Storage.removeItem("myKey"); + 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', () => { - expect(Storage.generatePath.bind(null, 'hello')).toThrow( - 'You need to call Parse.initialize before using Parse.' + it("can generate a unique storage path", () => { + expect(Storage.generatePath.bind(null, "hello")).toThrow( + "You need to call Parse.initialize before using Parse." ); - CoreManager.set('APPLICATION_ID', 'appid'); + CoreManager.set("APPLICATION_ID", "appid"); expect(Storage.generatePath.bind(null, 12)).toThrow( - 'Tried to get a Storage path that was not a String.' + "Tried to get a Storage path that was not a String." ); - expect(Storage.generatePath('hello')).toBe('Parse/appid/hello'); - expect(Storage.generatePath('/hello')).toBe('Parse/appid/hello'); + expect(Storage.generatePath("hello")).toBe("Parse/appid/hello"); + expect(Storage.generatePath("/hello")).toBe("Parse/appid/hello"); }); - it('can clear if controller does not implement clear', () => { + it("can clear if controller does not implement clear", () => { CoreManager.setStorageController({ getItem: () => {}, setItem: () => {}, @@ -299,45 +314,51 @@ describe('Storage (Default StorageController)', () => { }); }); -describe('Storage (Async StorageController)', () => { +describe("Storage (Async StorageController)", () => { beforeEach(() => { CoreManager.setAsyncStorage(mockRNStorageInterface); CoreManager.setStorageController( - require('../StorageController.react-native') + require("../StorageController.react-native") ); }); - it('throws when using a synchronous method', () => { + it("throws when using a synchronous method", () => { expect(Storage.getItem).toThrow( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); expect(Storage.setItem).toThrow( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); expect(Storage.removeItem).toThrow( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); expect(Storage.getAllKeys).toThrow( - 'Synchronous storage is not supported by the current storage controller' + "Synchronous storage is not supported by the current storage controller" ); }); - 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..ca21ca30d 100644 --- a/src/__tests__/TaskQueue-test.js +++ b/src/__tests__/TaskQueue-test.js @@ -9,19 +9,19 @@ jest.autoMockOff(); -const TaskQueue = require('../TaskQueue'); -const { resolvingPromise } = require('../promiseUtils'); +const TaskQueue = require("../TaskQueue"); +const { resolvingPromise } = require("../promiseUtils"); -describe('TaskQueue', () => { - it('is initialized with an empty queue', () => { +describe("TaskQueue", () => { + it("is initialized with an empty queue", () => { const q = new TaskQueue(); expect(q.queue).toEqual([]); }); - it('runs a single task immediately', async () => { + 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(() => { @@ -37,30 +37,34 @@ describe('TaskQueue', () => { 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; return p; }); expect(called).toBe(true); - reject('error'); + reject("error"); try { - await t - done.fail('should throw'); - } catch(e) { + await t; + done.fail("should throw"); + } catch (e) { done(); } - }) + }); - it('can execute a chain of tasks', async () => { + it("can execute a chain of tasks", async () => { const q = new TaskQueue(); const called = [false, false, false]; const completed = [false, false, false]; - const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; + const promises = [ + resolvingPromise(), + resolvingPromise(), + resolvingPromise(), + ]; q.enqueue(() => { called[0] = true; return promises[0].then(() => { @@ -82,25 +86,29 @@ describe('TaskQueue', () => { expect(called).toEqual([true, false, false]); expect(completed).toEqual([false, false, false]); promises[0].resolve(); - await new Promise(r => setImmediate(r)); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(completed).toEqual([true, false, false]); expect(q.queue.length).toBe(2); promises[1].resolve(); - await new Promise(r => setImmediate(r)); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(completed).toEqual([true, true, false]); expect(q.queue.length).toBe(1); promises[2].resolve(); - await new Promise(r => setImmediate(r)); + await new Promise((r) => setImmediate(r)); expect(completed).toEqual([true, true, true]); expect(q.queue.length).toBe(0); }); - it('continues the chain when a task errors', async () => { + it("continues the chain when a task errors", async () => { const q = new TaskQueue(); const called = [false, false, false]; - const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; + const promises = [ + resolvingPromise(), + resolvingPromise(), + resolvingPromise(), + ]; q.enqueue(() => { called[0] = true; return promises[0]; @@ -115,23 +123,27 @@ describe('TaskQueue', () => { }); expect(called).toEqual([true, false, false]); promises[0].catch(() => {}); - promises[0].reject('oops'); - await new Promise(r => setImmediate(r)); + promises[0].reject("oops"); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(q.queue.length).toBe(2); promises[1].resolve(); - await new Promise(r => setImmediate(r)); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(q.queue.length).toBe(1); promises[2].resolve(); - await new Promise(r => setImmediate(r)); + await new Promise((r) => setImmediate(r)); expect(q.queue.length).toBe(0); }); - it('continues the chain when all tasks errors', async () => { + it("continues the chain when all tasks errors", async () => { const q = new TaskQueue(); const called = [false, false, false]; - const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; + const promises = [ + resolvingPromise(), + resolvingPromise(), + resolvingPromise(), + ]; q.enqueue(() => { called[0] = true; return promises[0]; @@ -150,20 +162,20 @@ describe('TaskQueue', () => { expect(called).toEqual([true, false, false]); promises[0].catch(() => {}); - promises[0].reject('1 oops'); - await new Promise(r => setImmediate(r)); + promises[0].reject("1 oops"); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(q.queue.length).toBe(2); promises[1].catch(() => {}); - promises[1].reject('2 oops'); - await new Promise(r => setImmediate(r)); + promises[1].reject("2 oops"); + await new Promise((r) => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(q.queue.length).toBe(1); promises[2].catch(() => {}); - promises[2].reject('3 oops'); - await new Promise(r => setImmediate(r)); + promises[2].reject("3 oops"); + await new Promise((r) => setImmediate(r)); expect(q.queue.length).toBe(0); }); }); diff --git a/src/__tests__/UniqueInstanceStateController-test.js b/src/__tests__/UniqueInstanceStateController-test.js index 2f1dcf64f..0790a2cc7 100644 --- a/src/__tests__/UniqueInstanceStateController-test.js +++ b/src/__tests__/UniqueInstanceStateController-test.js @@ -7,48 +7,48 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ObjectStateMutations'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParseOp'); -jest.dontMock('../UniqueInstanceStateController'); -jest.dontMock('../TaskQueue'); -jest.dontMock('../promiseUtils'); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ObjectStateMutations"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParseOp"); +jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock("../TaskQueue"); +jest.dontMock("../promiseUtils"); jest.useFakeTimers(); -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; }; -mockObject.registerSubclass = function() {}; -jest.setMock('../ParseObject', mockObject); +mockObject.registerSubclass = function () {}; +jest.setMock("../ParseObject", mockObject); -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParseObject = require('../ParseObject'); -const ParseOps = require('../ParseOp'); -const UniqueInstanceStateController = require('../UniqueInstanceStateController'); -const TaskQueue = require('../TaskQueue'); -const { resolvingPromise } = require('../promiseUtils'); +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseObject = require("../ParseObject"); +const ParseOps = require("../ParseOp"); +const UniqueInstanceStateController = require("../UniqueInstanceStateController"); +const TaskQueue = require("../TaskQueue"); +const { resolvingPromise } = require("../promiseUtils"); -describe('UniqueInstanceStateController', () => { - it('returns null state for an unknown object', () => { +describe("UniqueInstanceStateController", () => { + it("returns null state for an unknown object", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); }); - it('returns empty data for an unknown object', () => { + it("returns empty data for an unknown object", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getServerData(obj)).toEqual({}); }); - it('returns an empty op queue for an unknown object', () => { + it("returns an empty op queue for an unknown object", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getPendingOps(obj)).toEqual([{}]); }); - it('initializes server data when setting state', () => { + it("initializes server data when setting state", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); @@ -57,11 +57,11 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can clear all data', () => { + it("can clear all data", () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -69,27 +69,27 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.clearAllState(); expect(UniqueInstanceStateController.getState(obj)).toEqual(null); }); - it('initializes server data when setting pending ops', () => { + it("initializes server data when setting pending ops", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can set server data on an existing state', () => { + it("can set server data on an existing state", () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -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,11 +113,11 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can remove server data from a state', () => { + it("can remove server data from a state", () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -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,65 +133,65 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can add multiple pending Ops', () => { + it("can add multiple pending Ops", () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); - UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); + UniqueInstanceStateController.setPendingOp(obj, "valid", op2); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op3 = new ParseOps.UnsetOp(); - UniqueInstanceStateController.setPendingOp(obj, 'valid', op3); + UniqueInstanceStateController.setPendingOp(obj, "valid", op3); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op3 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can unset pending Ops', () => { + it("can unset pending Ops", () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); - UniqueInstanceStateController.setPendingOp(obj, 'counter', null); + UniqueInstanceStateController.setPendingOp(obj, "counter", null); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can push a new pending state frame', () => { + it("can push a new pending state frame", () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -199,44 +199,44 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op2 = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); + UniqueInstanceStateController.setPendingOp(obj, "valid", op2); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }, { valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can pop a pending state frame', () => { + it("can pop a pending state frame", () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, 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, }); }); - it('will never leave the pending Op queue empty', () => { + it("will never leave the pending Op queue empty", () => { const obj = new ParseObject(); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -244,7 +244,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.popPendingState(obj); UniqueInstanceStateController.popPendingState(obj); @@ -253,62 +253,69 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); - it('can estimate a single attribute', () => { + 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); + expect( + UniqueInstanceStateController.estimateAttribute(obj, "counter") + ).toBe(11); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); - expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(12); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); + expect( + UniqueInstanceStateController.estimateAttribute(obj, "counter") + ).toBe(12); UniqueInstanceStateController.pushPendingState(obj); const op2 = new ParseOps.IncrementOp(10); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op2); - expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(22); + UniqueInstanceStateController.setPendingOp(obj, "counter", op2); + expect( + UniqueInstanceStateController.estimateAttribute(obj, "counter") + ).toBe(22); }); - it('can estimate all attributes', () => { + it("can estimate all attributes", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({}); UniqueInstanceStateController.setServerData(obj, { counter: 11 }); const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(false); - UniqueInstanceStateController.setPendingOp(obj, 'counter', op); - UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); + UniqueInstanceStateController.setPendingOp(obj, "counter", op); + 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); + UniqueInstanceStateController.setPendingOp(obj, "valid", op3); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ - counter: 12 + counter: 12, }); }); - it('can update server data with changes', () => { + it("can update server data with changes", () => { 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, }); }); - it('can enqueue a chain of tasks', async () => { + it("can enqueue a chain of tasks", async () => { const obj = new ParseObject(); const p1 = resolvingPromise(); const p2 = resolvingPromise(); @@ -339,57 +346,59 @@ describe('UniqueInstanceStateController', () => { expect(called).toEqual([true, true, true]); }); - it('can merge the first entry into the next', () => { + it("can merge the first entry into the next", () => { const obj = new ParseObject(); const incCount = new ParseOps.IncrementOp(1); - const setName = new ParseOps.SetOp('demo'); - UniqueInstanceStateController.setPendingOp(obj, 'counter', incCount); - UniqueInstanceStateController.setPendingOp(obj, 'name', setName); + const setName = new ParseOps.SetOp("demo"); + UniqueInstanceStateController.setPendingOp(obj, "counter", incCount); + UniqueInstanceStateController.setPendingOp(obj, "name", setName); UniqueInstanceStateController.pushPendingState(obj); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, 'counter', setCount); - UniqueInstanceStateController.setPendingOp(obj, 'valid', setValid); + UniqueInstanceStateController.setPendingOp(obj, "counter", setCount); + UniqueInstanceStateController.setPendingOp(obj, "valid", setValid); 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, }); }); - it('stores cached versions of object attributes', () => { + it("stores cached versions of object attributes", () => { const obj = new ParseObject(); let cache = UniqueInstanceStateController.getObjectCache(obj); expect(cache).toEqual({}); UniqueInstanceStateController.commitServerChanges(obj, { - name: 'MyObject', + 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' - }) + __type: "File", + name: "parse.txt", + url: "http://files.parsetfss.com/a/parse.txt", + }), }); cache = UniqueInstanceStateController.getObjectCache(obj); 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', + __type: "GeoPoint", latitude: 20, - longitude: 20 + longitude: 20, }); }); - it('can remove state for an object', () => { + it("can remove state for an object", () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.removeState(obj)).toBe(null); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); @@ -398,7 +407,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const state = UniqueInstanceStateController.removeState(obj); expect(state).toEqual({ @@ -406,13 +415,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() { + it("can allocate many objects without running out of memory", () => { + const closure = function () { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { spacious: true }); }; @@ -421,64 +430,69 @@ describe('UniqueInstanceStateController', () => { } }); - it('can duplicate the state of an object', () => { + 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); - UniqueInstanceStateController.setPendingOp(obj, 'valid', setValid); + UniqueInstanceStateController.setPendingOp(obj, "counter", setCount); + UniqueInstanceStateController.setPendingOp(obj, "valid", setValid); const duplicate = new ParseObject(); UniqueInstanceStateController.duplicateState(obj, duplicate); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: 'original' }, + serverData: { counter: 12, name: "original" }, 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' }, + 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' }, + serverData: { counter: 12, name: "duplicate" }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.commitServerChanges(obj, { o: { a: 12 } }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ - serverData: { counter: 12, name: 'original', o: { a: 12 } }, + serverData: { counter: 12, name: "original", o: { a: 12 } }, 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' }, + serverData: { counter: 12, name: "duplicate" }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const otherDup = new ParseObject(); UniqueInstanceStateController.duplicateState(obj, otherDup); expect(UniqueInstanceStateController.getState(otherDup)).toEqual({ - serverData: { counter: 12, name: 'original', o: { a: 12 } }, + serverData: { counter: 12, name: "original", o: { a: 12 } }, 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..f51140763 100644 --- a/src/__tests__/arrayContainsObject-test.js +++ b/src/__tests__/arrayContainsObject-test.js @@ -7,36 +7,38 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../arrayContainsObject'); +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++; + this._localId = "local" + localCount++; } -} -mockObject.prototype._getId = function() { +}; +mockObject.prototype._getId = function () { return this.id || this._localId; -} -jest.setMock('../ParseObject', mockObject); +}; +jest.setMock("../ParseObject", mockObject); -const arrayContainsObject = require('../arrayContainsObject').default; -const ParseObject = require('../ParseObject'); +const arrayContainsObject = require("../arrayContainsObject").default; +const ParseObject = require("../ParseObject"); -describe('arrayContainsObject', () => { - it('detects objects by their id', () => { - const o = new ParseObject('Item'); +describe("arrayContainsObject", () => { + it("detects objects by their id", () => { + const o = new ParseObject("Item"); expect(arrayContainsObject([], o)).toBe(false); - expect(arrayContainsObject([1, 'string'], 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..b51056223 100644 --- a/src/__tests__/browser-test.js +++ b/src/__tests__/browser-test.js @@ -1,15 +1,15 @@ -jest.dontMock('../CoreManager'); -jest.dontMock('../CryptoController'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../ParseError'); -jest.dontMock('../EventEmitter'); -jest.dontMock('../Parse'); -jest.dontMock('../RESTController'); -jest.dontMock('../Storage'); -jest.dontMock('crypto-js/aes'); +jest.dontMock("../CoreManager"); +jest.dontMock("../CryptoController"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../ParseError"); +jest.dontMock("../EventEmitter"); +jest.dontMock("../Parse"); +jest.dontMock("../RESTController"); +jest.dontMock("../Storage"); +jest.dontMock("crypto-js/aes"); -const ParseError = require('../ParseError').default; +const ParseError = require("../ParseError").default; class XMLHttpRequest {} class XDomainRequest { @@ -19,44 +19,46 @@ class XDomainRequest { global.XMLHttpRequest = XMLHttpRequest; global.XDomainRequest = XDomainRequest; -describe('Browser', () => { +describe("Browser", () => { beforeEach(() => { - process.env.PARSE_BUILD = 'browser'; + process.env.PARSE_BUILD = "browser"; jest.clearAllMocks(); }); afterEach(() => { - process.env.PARSE_BUILD = 'node'; + process.env.PARSE_BUILD = "node"; }); - it('warning initializing parse/node in browser', () => { - const Parse = require('../Parse'); - 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."); + it("warning initializing parse/node in browser", () => { + const Parse = require("../Parse"); + 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(Parse._initialize).toHaveBeenCalledTimes(1); }); - it('initializing parse/node in browser with server rendering', () => { + it("initializing parse/node in browser with server rendering", () => { process.env.SERVER_RENDERING = true; - const Parse = require('../Parse'); - jest.spyOn(console, 'log').mockImplementationOnce(() => {}); - jest.spyOn(Parse, '_initialize').mockImplementationOnce(() => {}); - Parse.initialize('A', 'B'); + const Parse = require("../Parse"); + jest.spyOn(console, "log").mockImplementationOnce(() => {}); + jest.spyOn(Parse, "_initialize").mockImplementationOnce(() => {}); + Parse.initialize("A", "B"); expect(console.log).toHaveBeenCalledTimes(0); expect(Parse._initialize).toHaveBeenCalledTimes(1); }); - it('load StorageController', () => { - const StorageController = require('../StorageController.browser'); - jest.spyOn(StorageController, 'setItem'); - const storage = require('../Storage'); - storage.setItem('key', 'value'); + it("load StorageController", () => { + const StorageController = require("../StorageController.browser"); + jest.spyOn(StorageController, "setItem"); + const storage = require("../Storage"); + storage.setItem("key", "value"); expect(StorageController.setItem).toHaveBeenCalledTimes(1); }); - it('load RESTController with IE9', async () => { + it("load RESTController with IE9", async () => { let called = false; class XDomainRequest { open() { @@ -69,65 +71,71 @@ describe('Browser', () => { } } global.XDomainRequest = XDomainRequest; - console.log('hererer'); - const RESTController = require('../RESTController'); + console.log("hererer"); + const RESTController = require("../RESTController"); const options = { 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); }); - it('RESTController IE9 Ajax timeout error', async () => { + it("RESTController IE9 Ajax timeout error", async () => { let called = false; class XDomainRequest { open() { called = true; } send() { - this.responseText = ''; + this.responseText = ""; this.ontimeout(); } } class XMLHttpRequest {} global.XDomainRequest = XDomainRequest; global.XMLHttpRequest = XMLHttpRequest; - const RESTController = require('../RESTController'); + const RESTController = require("../RESTController"); try { - await RESTController.ajax('POST', 'classes/TestObject'); + await RESTController.ajax("POST", "classes/TestObject"); expect(true).toBe(false); } 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); } expect(called).toBe(true); }); - it('RESTController IE9 Ajax response error', async () => { + it("RESTController IE9 Ajax response error", async () => { let called = false; class XDomainRequest { open() { called = true; } send() { - this.responseText = ''; + this.responseText = ""; this.onload(); } } class XMLHttpRequest {} global.XDomainRequest = XDomainRequest; global.XMLHttpRequest = XMLHttpRequest; - const RESTController = require('../RESTController'); + const RESTController = require("../RESTController"); try { - await RESTController.ajax('POST', 'classes/TestObject'); + await RESTController.ajax("POST", "classes/TestObject"); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe('Unexpected end of JSON input'); + expect(e.message).toBe("Unexpected end of JSON input"); } expect(called).toBe(true); }); diff --git a/src/__tests__/canBeSerialized-test.js b/src/__tests__/canBeSerialized-test.js index 45a1c14da..ab06c34eb 100644 --- a/src/__tests__/canBeSerialized-test.js +++ b/src/__tests__/canBeSerialized-test.js @@ -7,79 +7,79 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../canBeSerialized'); +jest.dontMock("../canBeSerialized"); function mockObject(id, attributes) { this.id = id; this.attributes = attributes; } -mockObject.registerSubclass = function() {}; -jest.setMock('../ParseObject', mockObject); +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); +jest.setMock("../ParseFile", mockFile); -const canBeSerialized = require('../canBeSerialized').default; -const ParseFile = require('../ParseFile'); -const ParseObject = require('../ParseObject'); -const ParseRelation = require('../ParseRelation').default; +const canBeSerialized = require("../canBeSerialized").default; +const ParseFile = require("../ParseFile"); +const ParseObject = require("../ParseObject"); +const ParseRelation = require("../ParseRelation").default; -describe('canBeSerialized', () => { - it('returns true for anything that is not a ParseObject', () => { +describe("canBeSerialized", () => { + it("returns true for anything that is not a ParseObject", () => { expect(canBeSerialized(12)).toBe(true); - expect(canBeSerialized('string')).toBe(true); + expect(canBeSerialized("string")).toBe(true); expect(canBeSerialized(false)).toBe(true); expect(canBeSerialized([])).toBe(true); expect(canBeSerialized({})).toBe(true); }); - it('validates primitives', () => { - const o = new ParseObject('oid', { + it("validates primitives", () => { + const o = new ParseObject("oid", { a: 12, - b: 'string', - c: false + b: "string", + 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() + it("returns false when a child is an unsaved object or file", () => { + let o = new ParseObject("oid", { + a: new ParseObject(), }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject('oid', { - a: new ParseObject('oid2', {}) + o = new ParseObject("oid", { + a: new ParseObject("oid2", {}), }); expect(canBeSerialized(o)).toBe(true); - o = new ParseObject('oid', { - a: new ParseFile() + o = new ParseObject("oid", { + a: new ParseFile(), }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject('oid', { - a: new ParseFile('http://files.parsetfss.com/a/parse.txt') + o = new ParseObject("oid", { + a: new ParseFile("http://files.parsetfss.com/a/parse.txt"), }); expect(canBeSerialized(o)).toBe(true); }); - it('returns true when all children have an id', () => { - const child = new ParseObject('child', {}); + 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); expect(canBeSerialized(child)).toBe(false); }); - it('returns true for relations', () => { + it("returns true for relations", () => { const relation = new ParseRelation(null, null); const parent = new ParseObject(undefined, { child: relation, @@ -87,40 +87,50 @@ describe('canBeSerialized', () => { expect(canBeSerialized(parent)).toBe(true); }); - it('traverses nested arrays and objects', () => { - let o = new ParseObject('oid', { + it("traverses nested arrays and objects", () => { + let o = new ParseObject("oid", { a: { a: { a: { - b: new ParseObject() - } - } - } + b: new ParseObject(), + }, + }, + }, }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject('oid', { + o = new ParseObject("oid", { 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() - }] + o = new ParseObject("oid", { + a: [ + 1, + 2, + 3, + { + b: new ParseObject(), + }, + ], }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject('oid', { - a: [1, 2, 3, { - b: new ParseObject('oid2') - }] + o = new ParseObject("oid", { + 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..4daf3c01a 100644 --- a/src/__tests__/decode-test.js +++ b/src/__tests__/decode-test.js @@ -7,119 +7,124 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../decode'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); -jest.dontMock('../ParsePolygon'); +jest.dontMock("../decode"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseGeoPoint"); +jest.dontMock("../ParsePolygon"); -const decode = require('../decode').default; +const decode = require("../decode").default; -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParseObject = require('../ParseObject').default; -const ParsePolygon = require('../ParsePolygon').default; +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseObject = require("../ParseObject").default; +const ParsePolygon = require("../ParsePolygon").default; -describe('decode', () => { - it('ignores primitives', () => { +describe("decode", () => { + it("ignores primitives", () => { expect(decode(undefined)).toBe(undefined); expect(decode(null)).toBe(null); expect(decode(true)).toBe(true); expect(decode(12)).toBe(12); - expect(decode('string')).toBe('string'); + expect(decode("string")).toBe("string"); }); - it('decodes dates', () => { - expect(decode({ - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' - })).toEqual(new Date(Date.UTC(2015, 1))); + it("decodes dates", () => { + expect( + decode({ + __type: "Date", + iso: "2015-02-01T00:00:00.000Z", + }) + ).toEqual(new Date(Date.UTC(2015, 1))); }); - it('decodes GeoPoints', () => { + it("decodes GeoPoints", () => { const point = decode({ - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 40.5, - longitude: 50.4 + longitude: 50.4, }); expect(point instanceof ParseGeoPoint).toBe(true); expect(point.latitude).toBe(40.5); expect(point.longitude).toBe(50.4); }); - it('decodes Polygons', () => { - const points = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + it("decodes Polygons", () => { + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const polygon = decode({ - __type: 'Polygon', + __type: "Polygon", coordinates: points, }); expect(polygon instanceof ParsePolygon).toBe(true); expect(polygon.coordinates).toEqual(points); }); - it('decodes Files', () => { + it("decodes Files", () => { const file = decode({ - __type: 'File', - name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "parse.txt", + url: "https://files.parsetfss.com/a/parse.txt", }); expect(file instanceof ParseFile).toBe(true); - expect(file.name()).toBe('parse.txt'); - expect(file.url()).toBe('https://files.parsetfss.com/a/parse.txt'); + expect(file.name()).toBe("parse.txt"); + expect(file.url()).toBe("https://files.parsetfss.com/a/parse.txt"); }); - it('decodes Relations', () => { + it("decodes Relations", () => { const obj = decode({ - __type: 'Relation', - className: 'Delivery' + __type: "Relation", + className: "Delivery", }); - expect(obj.constructor.mock.calls[0]).toEqual([ - null, - null - ]); - expect(obj.targetClassName).toBe('Delivery'); + expect(obj.constructor.mock.calls[0]).toEqual([null, null]); + expect(obj.targetClassName).toBe("Delivery"); }); - it('decodes Pointers', () => { + it("decodes Pointers", () => { const data = { - __type: 'Pointer', - className: 'Item', - objectId: '1001' + __type: "Pointer", + className: "Item", + objectId: "1001", }; decode(data); expect(ParseObject.fromJSON.mock.calls[0][0]).toEqual(data); }); - it('decodes ParseObjects', () => { + it("decodes ParseObjects", () => { const data = { - __type: 'Object', - className: 'Item', - objectId: '1001' + __type: "Object", + className: "Item", + 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([ - new Date(Date.UTC(2015, 1)), - 12, - 'string' - ]); + it("iterates over arrays", () => { + expect( + decode([ + { __type: "Date", iso: "2015-02-01T00:00:00.000Z" }, + 12, + "string", + ]) + ).toEqual([new Date(Date.UTC(2015, 1)), 12, "string"]); }); - it('iterates over objects', () => { - expect(decode({ - empty: null, - when: { __type: 'Date', iso: '2015-04-01T00:00:00.000Z' }, - count: 15 - })).toEqual({ + it("iterates over objects", () => { + 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..8d42d1173 100644 --- a/src/__tests__/encode-test.js +++ b/src/__tests__/encode-test.js @@ -7,27 +7,27 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../encode'); -jest.dontMock('../ParseACL'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseGeoPoint'); +jest.dontMock("../encode"); +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; }, toPointer() { - return 'POINTER'; + return "POINTER"; }, toOfflinePointer() { - return 'OFFLINE_POINTER'; + return "OFFLINE_POINTER"; }, _getId() { - return 'local1234'; + return "local1234"; }, dirty() {}, toJSON() { @@ -35,171 +35,177 @@ mockObject.prototype = { }, _toFullJSON(seen, offline) { const json = { - __type: 'Object', - className: this.className + __type: "Object", + className: this.className, }; for (const attr in this.attributes) { - json[attr] = encode(this.attributes[attr], false, false, seen.concat(this), offline); + json[attr] = encode( + this.attributes[attr], + false, + false, + seen.concat(this), + offline + ); } return json; - } + }, }; -jest.setMock('../ParseObject', mockObject); +jest.setMock("../ParseObject", mockObject); -const encode = require('../encode').default; -const ParseACL = require('../ParseACL').default; -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParseObject = require('../ParseObject'); -const ParseRelation = require('../ParseRelation').default; +const encode = require("../encode").default; +const ParseACL = require("../ParseACL").default; +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseObject = require("../ParseObject"); +const ParseRelation = require("../ParseRelation").default; -describe('encode', () => { - it('ignores primitives', () => { +describe("encode", () => { + it("ignores primitives", () => { expect(encode(undefined)).toBe(undefined); expect(encode(null)).toBe(null); expect(encode(true)).toBe(true); expect(encode(12)).toBe(12); - expect(encode('string')).toBe('string'); + expect(encode("string")).toBe("string"); }); - it('encodes dates', () => { + it("encodes dates", () => { expect(encode(new Date(Date.UTC(2015, 1)))).toEqual({ - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + __type: "Date", + iso: "2015-02-01T00:00:00.000Z", }); expect(encode.bind(null, new Date(Date.parse(null)))).toThrow( - 'Tried to encode an invalid date.' + "Tried to encode an invalid date." ); }); - it('encodes regular expressions', () => { - expect(encode(new RegExp('^hello'))).toEqual('^hello'); - expect(encode(/a[^b]+c/g)).toEqual('a[^b]+c'); + it("encodes regular expressions", () => { + expect(encode(new RegExp("^hello"))).toEqual("^hello"); + expect(encode(/a[^b]+c/g)).toEqual("a[^b]+c"); }); - it('encodes GeoPoints', () => { + it("encodes GeoPoints", () => { const point = new ParseGeoPoint(40.5, 50.4); expect(encode(point)).toEqual({ - __type: 'GeoPoint', + __type: "GeoPoint", latitude: 40.5, - longitude: 50.4 + longitude: 50.4, }); }); - it('encodes Files', () => { - const file = new ParseFile('parse.txt'); - expect(encode.bind(null, file)).toThrow('Tried to encode an unsaved file.'); - file._url = 'https://files.parsetfss.com/a/parse.txt'; + it("encodes Files", () => { + const file = new ParseFile("parse.txt"); + expect(encode.bind(null, file)).toThrow("Tried to encode an unsaved file."); + file._url = "https://files.parsetfss.com/a/parse.txt"; expect(encode(file)).toEqual({ - __type: 'File', - name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "parse.txt", + url: "https://files.parsetfss.com/a/parse.txt", }); }); - it('encodes Relations', () => { + it("encodes Relations", () => { const rel = new ParseRelation(); encode(rel); expect(rel.toJSON.mock.calls.length).toBe(1); }); - it('encodes ACLs', () => { + it("encodes ACLs", () => { const acl = new ParseACL({ aUserId: { read: true, write: false } }); expect(encode(acl)).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); - it('encodes ParseObjects', () => { - const obj = new ParseObject('Item'); + it("encodes ParseObjects", () => { + const obj = new ParseObject("Item"); obj._serverData = {}; - expect(encode(obj)).toEqual('POINTER'); + expect(encode(obj)).toEqual("POINTER"); obj._serverData = obj.attributes = { - str: 'string', - date: new Date(Date.UTC(2015, 1, 1)) + str: "string", + date: new Date(Date.UTC(2015, 1, 1)), }; expect(encode(obj)).toEqual({ - __type: 'Object', - className: 'Item', - str: 'string', + __type: "Object", + className: "Item", + str: "string", date: { - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' - } + __type: "Date", + iso: "2015-02-01T00:00:00.000Z", + }, }); obj.attributes.self = obj; expect(encode(obj)).toEqual({ - __type: 'Object', - className: 'Item', - str: 'string', + __type: "Object", + className: "Item", + str: "string", date: { - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + __type: "Date", + iso: "2015-02-01T00:00:00.000Z", }, - self: 'POINTER' + self: "POINTER", }); }); - it('encodes ParseObjects offline', () => { - const obj = new ParseObject('Item'); + it("encodes ParseObjects offline", () => { + const obj = new ParseObject("Item"); obj._serverData = {}; - expect(encode(obj, false, false, undefined, true)).toEqual('OFFLINE_POINTER'); + expect(encode(obj, false, false, undefined, true)).toEqual( + "OFFLINE_POINTER" + ); obj._serverData = obj.attributes = { - str: 'string', - date: new Date(Date.UTC(2015, 1, 1)) + str: "string", + date: new Date(Date.UTC(2015, 1, 1)), }; obj.attributes.self = obj; expect(encode(obj, false, false, undefined, true)).toEqual({ - __type: 'Object', - className: 'Item', - str: 'string', + __type: "Object", + className: "Item", + str: "string", date: { - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + __type: "Date", + 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'); + 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' + "Parse Objects not allowed here" ); }); - it('iterates over arrays', () => { - let arr = [12, new Date(Date.UTC(2015, 1)), 'str']; + 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' + { __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', () => { + 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' + date: { __type: "Date", iso: "2015-02-01T00:00:00.000Z" }, + str: "abc", }); }); }); diff --git a/src/__tests__/equals-test.js b/src/__tests__/equals-test.js index 3ed942e5f..50a8b1503 100644 --- a/src/__tests__/equals-test.js +++ b/src/__tests__/equals-test.js @@ -9,15 +9,15 @@ jest.autoMockOff(); -const equals = require('../equals').default; -const ParseACL = require('../ParseACL').default; -const ParseFile = require('../ParseFile').default; -const ParseGeoPoint = require('../ParseGeoPoint').default; -const ParseObject = require('../ParseObject').default; - -describe('equals', () => { - it('tests equality of primitives', () => { - expect(equals(1, 'string')).toBe(false); +const equals = require("../equals").default; +const ParseACL = require("../ParseACL").default; +const ParseFile = require("../ParseFile").default; +const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseObject = require("../ParseObject").default; + +describe("equals", () => { + it("tests equality of primitives", () => { + expect(equals(1, "string")).toBe(false); expect(equals(1, true)).toBe(false); expect(equals(1, undefined)).toBe(false); expect(equals(1, null)).toBe(false); @@ -25,13 +25,13 @@ describe('equals', () => { expect(equals(1, 4)).toBe(false); expect(equals(1, 1)).toBe(true); - expect(equals(null, 'string')).toBe(false); - expect(equals(true, 'string')).toBe(false); - expect(equals(undefined, 'string')).toBe(false); - expect(equals(true, 'string')).toBe(false); - expect(equals({}, 'string')).toBe(false); - expect(equals('abc', 'def')).toBe(false); - expect(equals('abc', 'abc')).toBe(true); + expect(equals(null, "string")).toBe(false); + expect(equals(true, "string")).toBe(false); + expect(equals(undefined, "string")).toBe(false); + expect(equals(true, "string")).toBe(false); + expect(equals({}, "string")).toBe(false); + expect(equals("abc", "def")).toBe(false); + expect(equals("abc", "abc")).toBe(true); expect(equals(false, false)).toBe(true); expect(equals(true, true)).toBe(true); @@ -42,7 +42,7 @@ describe('equals', () => { expect(equals(null, undefined)).toBe(false); }); - it('tests equality of objects and arrays', () => { + it("tests equality of objects and arrays", () => { const a = {}; expect(equals(a, a)).toBe(true); expect(equals({}, {})).toBe(true); @@ -60,7 +60,7 @@ describe('equals', () => { expect(equals([{ c: 3 }, 2, 1], [{ c: 3 }, 2, 1])).toBe(true); }); - it('tests equality of ACLs', () => { + it("tests equality of ACLs", () => { // Defer to ParseACL tests for the majority of testing const a = new ParseACL(); const b = new ParseACL(); @@ -75,7 +75,7 @@ describe('equals', () => { expect(equals(b, a)).toBe(false); }); - it('tests equality of GeoPoints', () => { + it("tests equality of GeoPoints", () => { // Defer to ParseGeoPoint tests for the majority of testing const a = new ParseGeoPoint(40, 40); expect(equals(a, a)).toBe(true); @@ -89,62 +89,62 @@ describe('equals', () => { expect(equals(b, a)).toBe(false); }); - it('tests equality of Files', () => { + it("tests equality of Files", () => { // Defer to ParseFile tests for the majority of testing - let a = new ParseFile('parse.txt', [61, 170, 236, 120]); - let b = new ParseFile('parse.txt', [61, 170, 236, 120]); + let a = new ParseFile("parse.txt", [61, 170, 236, 120]); + let b = new ParseFile("parse.txt", [61, 170, 236, 120]); expect(equals(a, a)).toBe(true); // unsaved files are never equal expect(equals(a, b)).toBe(false); a = ParseFile.fromJSON({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + __type: "File", + name: "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' + __type: "File", + name: "parse.txt", + url: "http://files.parsetfss.com/a/parse.txt", }); expect(equals(a, b)).toBe(true); }); - it('tests equality of ParseObjects', () => { + it("tests equality of ParseObjects", () => { // Defer to ParseObject tests for the majority of testing - const a = new ParseObject('Item'); - const b = new ParseObject('Item'); + const a = new ParseObject("Item"); + const b = new ParseObject("Item"); expect(equals(a, a)).toBe(true); expect(equals(a, b)).toBe(false); - a.id = 'myobj'; - b.id = 'myobj'; + a.id = "myobj"; + b.id = "myobj"; expect(equals(a, b)).toBe(true); const c = { - __type: 'Pointer', - className: 'Item', - objectId: 'myobj', + __type: "Pointer", + className: "Item", + objectId: "myobj", }; const d = { - __type: 'Object', - className: 'Item', - objectId: 'myobj', + __type: "Object", + className: "Item", + objectId: "myobj", }; const e = { - __type: 'Unknown', - className: 'Item', - objectId: 'myobj', + __type: "Unknown", + className: "Item", + objectId: "myobj", }; expect(equals(c, b)).toBe(true); expect(equals(d, b)).toBe(true); expect(equals(e, b)).toBe(false); }); - it('tests equality of Date', () => { - const a = new Date('2018-08-09T00:01:53.964Z'); - const b = new Date('2018-08-10T00:00:00.000Z'); + it("tests equality of Date", () => { + const a = new Date("2018-08-09T00:01:53.964Z"); + const b = new Date("2018-08-10T00:00:00.000Z"); expect(equals(a, a)).toBe(true); expect(equals(a, b)).toBe(false); diff --git a/src/__tests__/escape-test.js b/src/__tests__/escape-test.js index 0a4d7d10d..14a28d248 100644 --- a/src/__tests__/escape-test.js +++ b/src/__tests__/escape-test.js @@ -9,19 +9,20 @@ jest.autoMockOff(); -const escape = require('../escape.js').default; +const escape = require("../escape.js").default; -describe('escape', () => { - it('escapes special HTML characters', () => { - expect(escape('&')).toBe('&'); - expect(escape('<')).toBe('<'); - expect(escape('>')).toBe('>'); - expect(escape('\'')).toBe('''); - expect(escape('"')).toBe('"'); - expect(escape('/')).toBe('/'); +describe("escape", () => { + it("escapes special HTML characters", () => { + 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..2ed195c1b 100644 --- a/src/__tests__/parseDate-test.js +++ b/src/__tests__/parseDate-test.js @@ -9,19 +9,19 @@ jest.autoMockOff(); -const parseDate = require('../parseDate').default; +const parseDate = require("../parseDate").default; -describe('parseDate', () => { - it('returns a Date for valid strings', () => { - expect(Number(parseDate('2013-12-14T04:51:19.582Z'))).toBe( +describe("parseDate", () => { + it("returns a Date for valid strings", () => { + expect(Number(parseDate("2013-12-14T04:51:19.582Z"))).toBe( Number(new Date(Date.UTC(2013, 11, 14, 4, 51, 19, 582))) ); - expect(Number(parseDate('2013-12-14T04:51:19Z'))).toBe( + expect(Number(parseDate("2013-12-14T04:51:19Z"))).toBe( Number(new Date(Date.UTC(2013, 11, 14, 4, 51, 19))) ); }); - it('returns null for invalid strings', () => { - expect(parseDate('asdf')).toBe(null); + it("returns null for invalid strings", () => { + expect(parseDate("asdf")).toBe(null); }); -}) +}); diff --git a/src/__tests__/promiseUtils-test.js b/src/__tests__/promiseUtils-test.js index 41ff17ded..c7d1180d2 100644 --- a/src/__tests__/promiseUtils-test.js +++ b/src/__tests__/promiseUtils-test.js @@ -1,9 +1,9 @@ jest.autoMockOff(); -const { when } = require('../promiseUtils'); +const { when } = require("../promiseUtils"); -describe('promiseUtils', () => { - it('when', async () => { +describe("promiseUtils", () => { + it("when", async () => { const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); @@ -13,7 +13,7 @@ describe('promiseUtils', () => { result = await when(promise1, promise2); expect(result).toEqual([1, 2]); - result = await when(promise1, 'not a promise'); - expect(result).toEqual([1, 'not a promise']); + result = await when(promise1, "not a promise"); + expect(result).toEqual([1, "not a promise"]); }); }); diff --git a/src/__tests__/react-native-test.js b/src/__tests__/react-native-test.js index 3c5452bae..aac312480 100644 --- a/src/__tests__/react-native-test.js +++ b/src/__tests__/react-native-test.js @@ -1,73 +1,77 @@ /* global WebSocket */ -jest.dontMock('../CoreManager'); -jest.dontMock('../CryptoController'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../EventEmitter'); -jest.dontMock('../LiveQueryClient'); -jest.dontMock('../LocalDatastore'); -jest.dontMock('../ParseObject'); -jest.dontMock('../Storage'); +jest.dontMock("../CoreManager"); +jest.dontMock("../CryptoController"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../EventEmitter"); +jest.dontMock("../LiveQueryClient"); +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'); +const mockEmitter = require("../../../../react-native/Libraries/vendor/emitter/EventEmitter"); +const CoreManager = require("../CoreManager"); -describe('React Native', () => { +describe("React Native", () => { beforeEach(() => { - process.env.PARSE_BUILD = 'react-native'; + process.env.PARSE_BUILD = "react-native"; }); afterEach(() => { - process.env.PARSE_BUILD = 'node'; + process.env.PARSE_BUILD = "node"; }); - it('load EventEmitter', () => { - const eventEmitter = require('../EventEmitter'); + it("load EventEmitter", () => { + const eventEmitter = require("../EventEmitter"); expect(eventEmitter).toEqual(mockEmitter); }); - it('load CryptoController', () => { - const CryptoJS = require('react-native-crypto-js'); - jest.spyOn(CryptoJS.AES, 'encrypt').mockImplementation(() => { + it("load CryptoController", () => { + const CryptoJS = require("react-native-crypto-js"); + jest.spyOn(CryptoJS.AES, "encrypt").mockImplementation(() => { return { - toString: () => 'World', + toString: () => "World", }; }); - const CryptoController = require('../CryptoController'); - const phrase = CryptoController.encrypt({}, 'salt'); - expect(phrase).toBe('World'); + const CryptoController = require("../CryptoController"); + const phrase = CryptoController.encrypt({}, "salt"); + expect(phrase).toBe("World"); expect(CryptoJS.AES.encrypt).toHaveBeenCalled(); }); - it('load LocalDatastoreController', () => { - const LocalDatastoreController = require('../LocalDatastoreController.react-native'); - require('../LocalDatastore'); + it("load LocalDatastoreController", () => { + const LocalDatastoreController = require("../LocalDatastoreController.react-native"); + require("../LocalDatastore"); const LDC = CoreManager.getLocalDatastoreController(); expect(LocalDatastoreController).toEqual(LDC); }); - it('load StorageController', () => { - const StorageController = require('../StorageController.react-native'); - jest.spyOn(StorageController, 'setItemAsync'); - const storage = require('../Storage'); - storage.setItemAsync('key', 'value'); + it("load StorageController", () => { + const StorageController = require("../StorageController.react-native"); + jest.spyOn(StorageController, "setItemAsync"); + const storage = require("../Storage"); + storage.setItemAsync("key", "value"); expect(StorageController.setItemAsync).toHaveBeenCalledTimes(1); }); - it('load WebSocketController', () => { - jest.mock('../EventEmitter', () => { - return require('events').EventEmitter; + it("load WebSocketController", () => { + jest.mock("../EventEmitter", () => { + return require("events").EventEmitter; }); const socket = WebSocket; - require('../LiveQueryClient'); + require("../LiveQueryClient"); const websocket = CoreManager.getWebSocketController(); expect(websocket).toEqual(socket); }); diff --git a/src/__tests__/unique-test.js b/src/__tests__/unique-test.js index 40e082513..306ee99ff 100644 --- a/src/__tests__/unique-test.js +++ b/src/__tests__/unique-test.js @@ -7,58 +7,55 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../arrayContainsObject'); -jest.dontMock('../unique'); +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++; + this._localId = "local" + localCount++; } -} -mockObject.prototype._getId = function() { +}; +mockObject.prototype._getId = function () { return this.id || this._localId; -} -jest.setMock('../ParseObject', mockObject); +}; +jest.setMock("../ParseObject", mockObject); -const unique = require('../unique').default; -const ParseObject = require('../ParseObject'); +const unique = require("../unique").default; +const ParseObject = require("../ParseObject"); -describe('unique', () => { - it('produces an array with unique elements', () => { +describe("unique", () => { + it("produces an array with unique elements", () => { expect(unique([])).toEqual([]); expect(unique([1])).toEqual([1]); expect(unique([3, 4, 1])).toEqual([3, 4, 1]); expect(unique([3, 4, 3, 1])).toEqual([3, 4, 1]); expect(unique([2, 2, 2, 2, 2, 2, 2])).toEqual([2]); - expect(unique(['a', 'b', 'c', 'a', 'd'])).toEqual(['a', 'b', 'c', 'd']); + expect(unique(["a", "b", "c", "a", "d"])).toEqual(["a", "b", "c", "d"]); }); - it('dedups objects by their id', () => { - const o = new ParseObject('Item'); + 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..2e79c93e7 100644 --- a/src/__tests__/unsavedChildren-test.js +++ b/src/__tests__/unsavedChildren-test.js @@ -7,8 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock('../ParseFile'); -jest.dontMock('../unsavedChildren'); +jest.dontMock("../ParseFile"); +jest.dontMock("../unsavedChildren"); function mockObject({ className, localId, id, attributes, dirty }) { this.className = className; @@ -17,194 +17,188 @@ 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); +jest.setMock("../ParseObject", mockObject); -const ParseFile = require('../ParseFile').default; -const ParseObject = require('../ParseObject'); -const ParseRelation = require('../ParseRelation').default; -const unsavedChildren = require('../unsavedChildren').default; +const ParseFile = require("../ParseFile").default; +const ParseObject = require("../ParseObject"); +const ParseRelation = require("../ParseRelation").default; +const unsavedChildren = require("../unsavedChildren").default; -describe('unsavedChildren', () => { - it('finds unsaved files', () => { +describe("unsavedChildren", () => { + it("finds unsaved files", () => { 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("parse1.txt", [61, 170, 236, 120]), + new ParseFile("parse2.txt", [61, 170, 236, 120]), + new ParseFile("parse3.txt", [61, 170, 236, 120]), ]; const f = new ParseObject({ - className: 'Folder', - id: '121', + className: "Folder", + id: "121", attributes: { a: files[0], b: files[1], 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', () => { - const file = new ParseFile('parse1.txt', [61, 170, 236, 120]); + it("only returns unique files", () => { + const file = new ParseFile("parse1.txt", [61, 170, 236, 120]); const f = new ParseObject({ - className: 'Folder', - id: '121', + className: "Folder", + id: "121", attributes: { a: file, b: file, c: file, }, }); - expect(unsavedChildren(f)).toEqual([ file ]); + expect(unsavedChildren(f)).toEqual([file]); }); - it('finds unsaved child objects', () => { + it("finds unsaved child objects", () => { const a = new ParseObject({ - className: 'File', - localId: 'local0', + className: "File", + localId: "local0", attributes: {}, - dirty: true + dirty: true, }); const b = new ParseObject({ - className: 'File', - localId: 'local1', + className: "File", + localId: "local1", attributes: {}, - dirty: true + dirty: true, }); const f = new ParseObject({ - className: 'Folder', - id: '121', + 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', () => { + it("throws on nested objects without ids", () => { const a = new ParseObject({ - className: 'File', - localId: 'local0', + className: "File", + localId: "local0", attributes: {}, - dirty: true + dirty: true, }); const b = new ParseObject({ - className: 'File', - localId: 'local1', + className: "File", + localId: "local1", attributes: { - a: a + a: a, }, - dirty: true + dirty: true, }); const f = new ParseObject({ - className: 'Folder', - id: '121', + className: "Folder", + id: "121", attributes: { - b: b + b: b, }, }); expect(unsavedChildren.bind(null, f)).toThrow( - 'Cannot create a pointer to an unsaved Object.' + "Cannot create a pointer to an unsaved Object." ); }); - it('can explicitly allow nested objects without ids', () => { + it("can explicitly allow nested objects without ids", () => { const a = new ParseObject({ - className: 'Folder', - localId: 'local0', + className: "Folder", + localId: "local0", dirty: true, - attributes: {} + attributes: {}, }); const b = new ParseObject({ - className: 'Folder', - localId: 'local1', + className: "Folder", + localId: "local1", dirty: true, - attributes: {} + attributes: {}, }); const c = new ParseObject({ - className: 'File', - localId: 'local2', + 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', () => { + it("does not revisit objects", () => { const a = new ParseObject({ - className: 'File', - id: '130', + className: "File", + id: "130", attributes: { b: new ParseObject({ - className: 'File', - localId: '131', + 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', () => { + it("skips Relation", () => { const relation = new ParseRelation(null, null); const f = new ParseObject({ - className: 'Folder', - id: '121', + className: "Folder", + id: "121", attributes: { r: relation, }, diff --git a/src/__tests__/weapp-test.js b/src/__tests__/weapp-test.js index 01293e08b..1fa3339b0 100644 --- a/src/__tests__/weapp-test.js +++ b/src/__tests__/weapp-test.js @@ -1,65 +1,65 @@ -jest.dontMock('../CoreManager'); -jest.dontMock('../CryptoController'); -jest.dontMock('../decode'); -jest.dontMock('../encode'); -jest.dontMock('../EventEmitter'); -jest.dontMock('../LiveQueryClient'); -jest.dontMock('../Parse'); -jest.dontMock('../ParseFile'); -jest.dontMock('../ParseObject'); -jest.dontMock('../RESTController'); -jest.dontMock('../Socket.weapp'); -jest.dontMock('../Storage'); -jest.dontMock('crypto-js/aes'); -jest.dontMock('./test_helpers/mockWeChat'); +jest.dontMock("../CoreManager"); +jest.dontMock("../CryptoController"); +jest.dontMock("../decode"); +jest.dontMock("../encode"); +jest.dontMock("../EventEmitter"); +jest.dontMock("../LiveQueryClient"); +jest.dontMock("../Parse"); +jest.dontMock("../ParseFile"); +jest.dontMock("../ParseObject"); +jest.dontMock("../RESTController"); +jest.dontMock("../Socket.weapp"); +jest.dontMock("../Storage"); +jest.dontMock("crypto-js/aes"); +jest.dontMock("./test_helpers/mockWeChat"); -const CoreManager = require('../CoreManager'); -const mockWeChat = require('./test_helpers/mockWeChat'); +const CoreManager = require("../CoreManager"); +const mockWeChat = require("./test_helpers/mockWeChat"); global.wx = mockWeChat; -describe('WeChat', () => { +describe("WeChat", () => { beforeEach(() => { - process.env.PARSE_BUILD = 'weapp'; + process.env.PARSE_BUILD = "weapp"; }); afterEach(() => { - process.env.PARSE_BUILD = 'node'; + process.env.PARSE_BUILD = "node"; }); - it('load StorageController', () => { - const StorageController = require('../StorageController.weapp'); - jest.spyOn(StorageController, 'setItem'); - const storage = require('../Storage'); - storage.setItem('key', 'value'); + it("load StorageController", () => { + const StorageController = require("../StorageController.weapp"); + jest.spyOn(StorageController, "setItem"); + const storage = require("../Storage"); + storage.setItem("key", "value"); expect(StorageController.setItem).toHaveBeenCalledTimes(1); }); - it('load RESTController', () => { - const XHR = require('../Xhr.weapp'); - const RESTController = require('../RESTController'); + it("load RESTController", () => { + const XHR = require("../Xhr.weapp"); + const RESTController = require("../RESTController"); expect(RESTController._getXHR()).toEqual(XHR); }); - it('load ParseFile', () => { - const XHR = require('../Xhr.weapp'); - require('../ParseFile'); + it("load ParseFile", () => { + const XHR = require("../Xhr.weapp"); + require("../ParseFile"); const fileController = CoreManager.getFileController(); expect(fileController._getXHR()).toEqual(XHR); }); - it('load WebSocketController', () => { - const socket = require('../Socket.weapp'); - require('../LiveQueryClient'); + it("load WebSocketController", () => { + const socket = require("../Socket.weapp"); + require("../LiveQueryClient"); const websocket = CoreManager.getWebSocketController(); expect(websocket).toEqual(socket); }); - describe('Socket', () => { - it('send', () => { - const Websocket = require('../Socket.weapp'); - jest.spyOn(mockWeChat, 'connectSocket'); - const socket = new Websocket('wss://examples.com'); + describe("Socket", () => { + it("send", () => { + const Websocket = require("../Socket.weapp"); + jest.spyOn(mockWeChat, "connectSocket"); + const socket = new Websocket("wss://examples.com"); socket.onopen(); socket.onmessage(); socket.onclose(); @@ -71,7 +71,7 @@ describe('WeChat', () => { expect(mockWeChat.connectSocket).toHaveBeenCalled(); - socket.send('{}'); + socket.send("{}"); expect(socket.onopen).toHaveBeenCalled(); expect(socket.onmessage).toHaveBeenCalled(); diff --git a/src/arrayContainsObject.js b/src/arrayContainsObject.js index 791e2c2f8..752b92a6d 100644 --- a/src/arrayContainsObject.js +++ b/src/arrayContainsObject.js @@ -9,7 +9,7 @@ * @flow */ -import ParseObject from './ParseObject'; +import ParseObject from "./ParseObject"; export default function arrayContainsObject( array: Array, @@ -19,7 +19,8 @@ export default function arrayContainsObject( 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/canBeSerialized.js b/src/canBeSerialized.js index 417a1f1fe..3145d95b0 100644 --- a/src/canBeSerialized.js +++ b/src/canBeSerialized.js @@ -9,9 +9,9 @@ * @flow */ -import ParseFile from './ParseFile'; -import ParseObject from './ParseObject'; -import ParseRelation from './ParseRelation'; +import ParseFile from "./ParseFile"; +import ParseObject from "./ParseObject"; +import ParseRelation from "./ParseRelation"; export default function canBeSerialized(obj: ParseObject): boolean { if (!(obj instanceof ParseObject)) { @@ -28,7 +28,7 @@ export default function canBeSerialized(obj: ParseObject): boolean { } function canBeSerializedHelper(value: any): boolean { - if (typeof value !== 'object') { + if (typeof value !== "object") { return true; } if (value instanceof ParseRelation) { diff --git a/src/decode.js b/src/decode.js index 209c80824..41cf6f213 100644 --- a/src/decode.js +++ b/src/decode.js @@ -8,16 +8,16 @@ * * @flow */ -import ParseACL from './ParseACL'; // eslint-disable-line no-unused-vars -import ParseFile from './ParseFile'; -import ParseGeoPoint from './ParseGeoPoint'; -import ParsePolygon from './ParsePolygon'; -import ParseObject from './ParseObject'; -import { opFromJSON } from './ParseOp'; -import ParseRelation from './ParseRelation'; +import ParseACL from "./ParseACL"; // eslint-disable-line no-unused-vars +import ParseFile from "./ParseFile"; +import ParseGeoPoint from "./ParseGeoPoint"; +import ParsePolygon from "./ParsePolygon"; +import ParseObject from "./ParseObject"; +import { opFromJSON } from "./ParseOp"; +import ParseRelation from "./ParseRelation"; export default function decode(value: any): any { - if (value === null || typeof value !== 'object') { + if (value === null || typeof value !== "object") { return value; } if (Array.isArray(value)) { @@ -27,34 +27,34 @@ export default function decode(value: any): any { }); return dup; } - if (typeof value.__op === 'string') { + if (typeof value.__op === "string") { return opFromJSON(value); } - if (value.__type === 'Pointer' && value.className) { + if (value.__type === "Pointer" && value.className) { return ParseObject.fromJSON(value); } - if (value.__type === 'Object' && value.className) { + if (value.__type === "Object" && value.className) { return ParseObject.fromJSON(value); } - if (value.__type === 'Relation') { + if (value.__type === "Relation") { // The parent and key fields will be populated by the parent const relation = new ParseRelation(null, null); relation.targetClassName = value.className; return relation; } - if (value.__type === 'Date') { + if (value.__type === "Date") { return new Date(value.iso); } - if (value.__type === 'File') { + if (value.__type === "File") { return ParseFile.fromJSON(value); } - if (value.__type === 'GeoPoint') { + if (value.__type === "GeoPoint") { return new ParseGeoPoint({ latitude: value.latitude, - longitude: value.longitude + longitude: value.longitude, }); } - if (value.__type === 'Polygon') { + if (value.__type === "Polygon") { return new ParsePolygon(value.coordinates); } const copy = {}; diff --git a/src/encode.js b/src/encode.js index 41e0e798a..1b000d2b1 100644 --- a/src/encode.js +++ b/src/encode.js @@ -9,27 +9,34 @@ * @flow */ -import ParseACL from './ParseACL'; -import ParseFile from './ParseFile'; -import ParseGeoPoint from './ParseGeoPoint'; -import ParsePolygon from './ParsePolygon'; -import ParseObject from './ParseObject'; -import { Op } from './ParseOp'; -import ParseRelation from './ParseRelation'; +import ParseACL from "./ParseACL"; +import ParseFile from "./ParseFile"; +import ParseGeoPoint from "./ParseGeoPoint"; +import ParsePolygon from "./ParsePolygon"; +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'); + throw new Error("Parse Objects not allowed here"); } - const seenEntry = value.id ? value.className + ':' + value.id : value; - if (forcePointers || + const seenEntry = value.id ? value.className + ":" + value.id : value; + if ( + forcePointers || !seen || seen.indexOf(seenEntry) > -1 || value.dirty() || Object.keys(value._getServerData()).length < 1 ) { - if (offline && value._getId().startsWith('local')) { + if (offline && value._getId().startsWith("local")) { return value.toOfflinePointer(); } return value.toPointer(); @@ -37,27 +44,31 @@ 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) { if (!value.url()) { - throw new Error('Tried to encode an unsaved file.'); + throw new Error("Tried to encode an unsaved file."); } return value.toJSON(); } - if (Object.prototype.toString.call(value) === '[object Date]') { + if (Object.prototype.toString.call(value) === "[object Date]") { if (isNaN(value)) { - throw new Error('Tried to encode an invalid date.'); + throw new Error("Tried to encode an invalid date."); } - return { __type: 'Date', iso: (value: any).toJSON() }; + 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; } @@ -67,10 +78,16 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean, }); } - if (value && typeof value === 'object') { + if (value && typeof value === "object") { const output = {}; for (const k in value) { - output[k] = encode(value[k], disallowObjects, forcePointers, seen, offline); + output[k] = encode( + value[k], + disallowObjects, + forcePointers, + seen, + offline + ); } return output; } @@ -78,6 +95,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..807bc159a 100644 --- a/src/equals.js +++ b/src/equals.js @@ -7,26 +7,29 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import ParseACL from './ParseACL'; -import ParseFile from './ParseFile'; -import ParseGeoPoint from './ParseGeoPoint'; -import ParseObject from './ParseObject'; +import ParseACL from "./ParseACL"; +import ParseFile from "./ParseFile"; +import ParseGeoPoint from "./ParseGeoPoint"; +import ParseObject from "./ParseObject"; export default function equals(a, b) { const toString = Object.prototype.toString; - if (toString.call(a) === '[object Date]' || toString.call(b) === '[object Date]') { + 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) { return false; } - if (!a || typeof a !== 'object') { + if (!a || typeof a !== "object") { // a is a primitive - return (a === b); + return a === b; } if (Array.isArray(a) || Array.isArray(b)) { @@ -44,14 +47,16 @@ 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) { - if (a.__type === 'Object' || a.__type === 'Pointer') { + if (a.__type === "Object" || a.__type === "Pointer") { return a.objectId === b.id && a.className === b.className; } } diff --git a/src/escape.js b/src/escape.js index a56eeb1f3..eaa0ff15a 100644 --- a/src/escape.js +++ b/src/escape.js @@ -10,16 +10,16 @@ */ 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..c124101fc 100644 --- a/src/interfaces/react-native.js +++ b/src/interfaces/react-native.js @@ -12,9 +12,19 @@ */ 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; - static removeItem(path: string, cb: (err: string, value: string) => void): void; + static getItem( + path: string, + cb: (err: string, value: string) => void + ): void; + static setItem( + path: string, + value: string, + cb: (err: string, value: string) => void + ): void; + static removeItem( + path: string, + cb: (err: string, value: string) => void + ): void; static getAllKeys(cb: (err: string, keys: Array) => void): void; static clear(): void; } diff --git a/src/isRevocableSession.js b/src/isRevocableSession.js index a6a8a23b8..f0df86aca 100644 --- a/src/isRevocableSession.js +++ b/src/isRevocableSession.js @@ -10,5 +10,5 @@ */ export default function isRevocableSession(token: string): boolean { - return token.indexOf('r:') > -1; + return token.indexOf("r:") > -1; } diff --git a/src/parseDate.js b/src/parseDate.js index 936fb602e..bf50916d3 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..9be27de6c 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..1b5d385f0 100644 --- a/src/unique.js +++ b/src/unique.js @@ -9,8 +9,8 @@ * @flow */ -import arrayContainsObject from './arrayContainsObject'; -import ParseObject from './ParseObject'; +import arrayContainsObject from "./arrayContainsObject"; +import ParseObject from "./ParseObject"; export default function unique(arr: Array): Array { const uniques = []; diff --git a/src/unsavedChildren.js b/src/unsavedChildren.js index 512173efa..5996a67af 100644 --- a/src/unsavedChildren.js +++ b/src/unsavedChildren.js @@ -9,13 +9,13 @@ * @flow */ -import ParseFile from './ParseFile'; -import ParseObject from './ParseObject'; -import ParseRelation from './ParseRelation'; +import ParseFile from "./ParseFile"; +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,15 +32,13 @@ export default function unsavedChildren( ): Array { const encountered = { objects: {}, - files: [] + files: [], }; - const identifier = obj.className + ':' + obj._getId(); - encountered.objects[identifier] = ( - obj.dirty() ? obj : true - ); + const identifier = obj.className + ":" + obj._getId(); + encountered.objects[identifier] = obj.dirty() ? obj : true; const attributes = obj.attributes; for (const attr in attributes) { - if (typeof attributes[attr] === 'object') { + if (typeof attributes[attr] === "object") { traverse(attributes[attr], encountered, false, !!allowDeepUnsaved); } } @@ -61,17 +59,20 @@ function traverse( ) { if (obj instanceof ParseObject) { if (!obj.id && shouldThrow) { - throw new Error('Cannot create a pointer to an unsaved Object.'); + throw new Error("Cannot create a pointer to an unsaved Object."); } - const identifier = obj.className + ':' + obj._getId(); + 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') { - traverse(attributes[attr], encountered, !allowDeepUnsaved, allowDeepUnsaved); + if (typeof attributes[attr] === "object") { + traverse( + attributes[attr], + encountered, + !allowDeepUnsaved, + allowDeepUnsaved + ); } } } @@ -88,13 +89,13 @@ function traverse( } if (Array.isArray(obj)) { obj.forEach((el) => { - if (typeof el === 'object') { + if (typeof el === "object") { traverse(el, encountered, shouldThrow, allowDeepUnsaved); } }); } for (const k in obj) { - if (typeof obj[k] === 'object') { + if (typeof obj[k] === "object") { traverse(obj[k], encountered, shouldThrow, allowDeepUnsaved); } } From 479961fbf4a8c2451aebc52f0d254795df48cdf5 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 12:47:02 +0100 Subject: [PATCH 03/11] Add config --- .prettierrc | 5 + integration/cloud/main.js | 38 +- integration/server.js | 40 +- integration/test/ArrayOperationsTest.js | 460 ++- integration/test/DirtyTest.js | 152 +- integration/test/IdempotencyTest.js | 76 +- integration/test/IncrementTest.js | 164 +- integration/test/ParseACLTest.js | 256 +- integration/test/ParseCloudTest.js | 130 +- integration/test/ParseConfigTest.js | 47 +- integration/test/ParseFileTest.js | 88 +- integration/test/ParseGeoBoxTest.js | 104 +- integration/test/ParseGeoPointTest.js | 340 +-- integration/test/ParseLiveQueryTest.js | 160 +- integration/test/ParseLocalDatastoreTest.js | 1475 +++++---- integration/test/ParseMasterKeyTest.js | 34 +- integration/test/ParseObjectTest.js | 1341 ++++---- integration/test/ParsePolygonTest.js | 66 +- integration/test/ParseQueryAggregateTest.js | 95 +- integration/test/ParseQueryTest.js | 1690 +++++------ integration/test/ParseRelationTest.js | 168 +- integration/test/ParseRoleTest.js | 16 +- integration/test/ParseSchemaTest.js | 380 ++- integration/test/ParseSubclassTest.js | 76 +- integration/test/ParseUserTest.js | 641 ++-- integration/test/clear.js | 4 +- integration/test/helper.js | 12 +- integration/test/mockLocalStorage.js | 2 +- integration/test/mockRNStorage.js | 4 +- src/Analytics.js | 25 +- src/AnonymousUtils.js | 20 +- src/Cloud.js | 60 +- src/CoreManager.js | 320 +- src/CryptoController.js | 8 +- src/EventEmitter.js | 6 +- src/FacebookUtils.js | 52 +- src/InstallationController.js | 10 +- src/LiveQueryClient.js | 138 +- src/LiveQuerySubscription.js | 12 +- src/LocalDatastore.js | 66 +- src/LocalDatastoreController.js | 6 +- src/LocalDatastoreController.react-native.js | 14 +- src/LocalDatastoreUtils.js | 10 +- src/ObjectStateMutations.js | 33 +- src/OfflineQuery.js | 184 +- src/Parse.js | 122 +- src/ParseACL.js | 87 +- src/ParseConfig.js | 81 +- src/ParseError.js | 4 +- src/ParseFile.js | 223 +- src/ParseGeoPoint.js | 40 +- src/ParseHooks.js | 57 +- src/ParseInstallation.js | 10 +- src/ParseLiveQuery.js | 44 +- src/ParseObject.js | 575 ++-- src/ParseOp.js | 150 +- src/ParsePolygon.js | 31 +- src/ParseQuery.js | 580 ++-- src/ParseRelation.js | 36 +- src/ParseRole.js | 40 +- src/ParseSchema.js | 105 +- src/ParseSession.js | 53 +- src/ParseUser.js | 360 +-- src/Push.js | 16 +- src/RESTController.js | 185 +- src/SingleInstanceStateController.js | 34 +- src/Socket.weapp.js | 4 +- src/Storage.js | 46 +- src/StorageController.react-native.js | 2 +- src/TaskQueue.js | 6 +- src/UniqueInstanceStateController.js | 30 +- src/Xhr.weapp.js | 20 +- src/__tests__/Analytics-test.js | 69 +- src/__tests__/AnonymousUtils-test.js | 44 +- src/__tests__/Cloud-test.js | 184 +- src/__tests__/CoreManager-test.js | 124 +- src/__tests__/FacebookUtils-test.js | 177 +- src/__tests__/Hooks-test.js | 217 +- src/__tests__/InstallationController-test.js | 48 +- src/__tests__/LiveQueryClient-test.js | 702 +++-- src/__tests__/LocalDatastore-test.js | 437 ++- src/__tests__/ObjectStateMutations-test.js | 176 +- src/__tests__/OfflineQuery-test.js | 770 +++-- src/__tests__/Parse-test.js | 166 +- src/__tests__/ParseACL-test.js | 192 +- src/__tests__/ParseConfig-test.js | 187 +- src/__tests__/ParseError-test.js | 22 +- src/__tests__/ParseFile-test.js | 774 +++-- src/__tests__/ParseGeoPoint-test.js | 36 +- src/__tests__/ParseInstallation-test.js | 34 +- src/__tests__/ParseLiveQuery-test.js | 237 +- src/__tests__/ParseObject-test.js | 2703 ++++++++--------- src/__tests__/ParseOp-test.js | 348 +-- src/__tests__/ParsePolygon-test.js | 28 +- src/__tests__/ParseQuery-test.js | 2475 ++++++++------- src/__tests__/ParseRelation-test.js | 274 +- src/__tests__/ParseRole-test.js | 73 +- src/__tests__/ParseSchema-test.js | 310 +- src/__tests__/ParseSession-test.js | 144 +- src/__tests__/ParseUser-test.js | 1124 ++++--- src/__tests__/Push-test.js | 58 +- src/__tests__/RESTController-test.js | 537 ++-- .../SingleInstanceStateController-test.js | 472 ++- src/__tests__/Storage-test.js | 284 +- src/__tests__/TaskQueue-test.js | 70 +- .../UniqueInstanceStateController-test.js | 166 +- src/__tests__/arrayContainsObject-test.js | 26 +- src/__tests__/browser-test.js | 86 +- src/__tests__/canBeSerialized-test.js | 60 +- src/__tests__/decode-test.js | 92 +- src/__tests__/encode-test.js | 162 +- src/__tests__/equals-test.js | 90 +- src/__tests__/escape-test.js | 22 +- src/__tests__/parseDate-test.js | 14 +- src/__tests__/promiseUtils-test.js | 10 +- src/__tests__/react-native-test.js | 74 +- src/__tests__/unique-test.js | 44 +- src/__tests__/unsavedChildren-test.js | 98 +- src/__tests__/weapp-test.js | 78 +- src/arrayContainsObject.js | 7 +- src/canBeSerialized.js | 8 +- src/decode.js | 32 +- src/encode.js | 44 +- src/equals.js | 17 +- src/escape.js | 12 +- src/interfaces/react-native.js | 18 +- src/isRevocableSession.js | 2 +- src/parseDate.js | 10 +- src/promiseUtils.js | 2 +- src/unique.js | 6 +- src/unsavedChildren.js | 29 +- 131 files changed, 12475 insertions(+), 14199 deletions(-) create mode 100644 .prettierrc 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 c193689db..f94f981d8 100644 --- a/integration/cloud/main.js +++ b/integration/cloud/main.js @@ -1,51 +1,51 @@ /* global Parse */ -Parse.Cloud.define("bar", function (request) { - if (request.params.key2 === "value1") { - return "Foo"; +Parse.Cloud.define('bar', function (request) { + if (request.params.key2 === 'value1') { + return 'Foo'; } else { - throw "bad stuff happened"; + throw 'bad stuff happened'; } }); -Parse.Cloud.define("TestFetchFromLocalDatastore", function (request) { - const object = new Parse.Object("Item"); +Parse.Cloud.define('TestFetchFromLocalDatastore', function (request) { + const object = new Parse.Object('Item'); object.id = request.params.id; - object.set("foo", "changed"); + object.set('foo', 'changed'); return object.save(); }); -Parse.Cloud.define("UpdateUser", function (request) { +Parse.Cloud.define('UpdateUser', function (request) { const user = new Parse.User(); user.id = request.params.id; - user.set("foo", "changed"); + user.set('foo', 'changed'); return user.save(null, { useMasterKey: true }); }); -Parse.Cloud.define("CloudFunctionIdempotency", function () { - const object = new Parse.Object("IdempotencyItem"); +Parse.Cloud.define('CloudFunctionIdempotency', function () { + const object = new Parse.Object('IdempotencyItem'); 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) => { +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 () { - throw "cloud job failed"; +Parse.Cloud.job('CloudJobFailing', function () { + throw 'cloud job failed'; }); diff --git a/integration/server.js b/integration/server.js index 4d2801e93..69af1b260 100644 --- a/integration/server.js +++ b/integration/server.js @@ -1,40 +1,36 @@ -const express = require("express"); -const ParseServer = require("parse-server").ParseServer; +const express = require('express'); +const ParseServer = require('parse-server').ParseServer; const app = express(); -const CustomAuth = require("./test/CustomAuth"); +const CustomAuth = require('./test/CustomAuth'); const api = new ParseServer({ - databaseURI: "mongodb://localhost:27017/integration", - appId: "integration", - masterKey: "notsosecret", - serverURL: "http://localhost:1337/parse", + databaseURI: 'mongodb://localhost:27017/integration', + appId: 'integration', + masterKey: 'notsosecret', + serverURL: 'http://localhost:1337/parse', cloud: `${__dirname}/cloud/main.js`, liveQuery: { - classNames: ["TestObject", "DiffObject"], + classNames: ['TestObject', 'DiffObject'], }, startLiveQueryServer: true, auth: { myAuth: { module: CustomAuth, - option1: "hello", - option2: "world", + option1: 'hello', + 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", - ], + paths: ['functions/CloudFunctionIdempotency', 'jobs/CloudJob1', 'classes/IdempotentTest'], ttl: 120, }, serverStartComplete: () => { @@ -42,14 +38,14 @@ const api = new ParseServer({ }, }); -app.use("/parse", api); +app.use('/parse', api); -const TestUtils = require("parse-server").TestUtils; +const TestUtils = require('parse-server').TestUtils; -app.get("/clear/:fast", (req, res) => { +app.get('/clear/:fast', (req, res) => { const { fast } = req.params; TestUtils.destroyAllDataPermanently(fast).then(() => { - res.send("{}"); + res.send('{}'); }); }); diff --git a/integration/test/ArrayOperationsTest.js b/integration/test/ArrayOperationsTest.js index 803f66aa9..cb9f6f838 100644 --- a/integration/test/ArrayOperationsTest.js +++ b/integration/test/ArrayOperationsTest.js @@ -1,120 +1,120 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -describe("Array Operations", () => { - beforeAll((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Array Operations', () => { + 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) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar", "baz"]); + 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"); + const query = new Parse.Query('TestObject'); return query.get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + assert.equal(strings[0], 'foo'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); done(); }); }); - it("adds values", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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"); + object.add('strings', 'foo'); + object.add('strings', 'bar'); + object.add('strings', 'baz'); return object.save(); }) .then(() => { - const query = new Parse.Query("TestObject"); + const query = new Parse.Query('TestObject'); return query.get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + 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) => { - const object = new Parse.Object("TestObject"); - object.add("strings", "foo"); - object.add("strings", "bar"); - object.add("strings", "baz"); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + assert.equal(strings[0], 'foo'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); done(); }); }); - it("sets then adds objects", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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"); + object.set('strings', ['bar']); + object.add('strings', 'bar'); + object.add('strings', 'baz'); return object.save(); }) .then(() => { - return new Parse.Query("TestObject").get(object.id); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + assert.equal(strings[0], 'bar'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); done(); }); }); - it("adds values atomically", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { + .then(o => { assert(o !== object); - o.add("strings", "bar"); - o.add("strings", "baz"); - object.add("strings", "bar"); - object.add("strings", "baz"); + o.add('strings', 'bar'); + o.add('strings', 'baz'); + object.add('strings', 'bar'); + object.add('strings', 'baz'); return o.save(); }) .then(() => { @@ -122,85 +122,85 @@ describe("Array Operations", () => { return object.save(); }) .then(() => { - return new Parse.Query("TestObject").get(object.id); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .then(o => { + const strings = o.get('strings'); assert.equal(strings.length, 5); done(); }); }); - it("adds unique values", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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"); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + 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) => { - const object = new Parse.Object("TestObject"); - object.addUnique("strings", "foo"); - object.addUnique("strings", "bar"); - object.addUnique("strings", "foo"); - object.addUnique("strings", "baz"); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + 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.addUnique("numbers", number); + 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.addUnique('numbers', number); }); - assert.equal(object.get("numbers").length, 7); + assert.equal(object.get('numbers').length, 7); }); - it("adds unique values atomically", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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); + 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"); + .then(o => { + o.addUnique('strings', 'bar'); + o.addUnique('strings', 'baz'); + object.addUnique('strings', 'baz'); + object.addUnique('strings', 'bat'); return o.save(); }) .then(() => { @@ -208,95 +208,95 @@ describe("Array Operations", () => { return object.save(); }) .then(() => { - return new Parse.Query("TestObject").get(object.id); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .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"); + 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) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "foo", "bar", "baz"]); + 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"); + object.remove('strings', 'foo'); + object.remove('strings', 'baz'); + object.remove('strings', 'bat'); return object.save(); }) .then(() => { - return new Parse.Query("TestObject").get(object.id); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .then(o => { + const strings = o.get('strings'); assert.equal(strings.length, 1); - assert.equal(strings[0], "bar"); + assert.equal(strings[0], 'bar'); done(); }); }); - it("sets then removes values", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo"]); + 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"); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .then(o => { + const strings = o.get('strings'); assert.equal(strings.length, 1); - assert.equal(strings[0], "bat"); + assert.equal(strings[0], 'bat'); 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"); + 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); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .then(o => { + const strings = o.get('strings'); assert.equal(strings.length, 0); done(); }); }); - it("removes values atomically", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "foo", "bar", "baz"]); + 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); + 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"); + .then(o => { + o.remove('strings', 'foo'); + o.remove('strings', 'zzz'); + object.remove('strings', 'bar'); + object.remove('strings', 'zzz'); return o.save(); }) .then(() => { @@ -304,172 +304,166 @@ describe("Array Operations", () => { return object.save(); }) .then(() => { - return new Parse.Query("TestObject").get(object.id); + return new Parse.Query('TestObject').get(object.id); }) - .then((o) => { - const strings = o.get("strings"); + .then(o => { + const strings = o.get('strings'); strings.sort(); assert.equal(strings.length, 1); - assert.equal(strings[0], "baz"); + assert.equal(strings[0], 'baz'); done(); }); }); - it("fails when combining add unique with add", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.add('strings', 'bar'); + object.addUnique('strings', 'bar'); }) - .catch((e) => { - assert.equal( - e.message, - "Cannot merge AddUnique Op with the previous Op" - ); + .catch(e => { + assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); done(); }); }); - it("fails when combining add with add unique", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.addUnique('strings', 'bar'); + object.add('strings', 'bar'); }) - .catch((e) => { - assert.equal(e.message, "Cannot merge Add Op with the previous Op"); + .catch(e => { + assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); done(); }); }); - it("fails when combining remove with add", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.add('strings', 'bar'); + object.remove('strings', 'bar'); }) - .catch((e) => { - assert.equal(e.message, "Cannot merge Remove Op with the previous Op"); + .catch(e => { + assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); done(); }); }); - it("fails when combining add with remove", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.remove('strings', 'bar'); + object.add('strings', 'bar'); }) - .catch((e) => { - assert.equal(e.message, "Cannot merge Add Op with the previous Op"); + .catch(e => { + assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); done(); }); }); - it("fails when combining remove with add unique", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.addUnique('strings', 'bar'); + object.remove('strings', 'bar'); }) - .catch((e) => { - assert.equal(e.message, "Cannot merge Remove Op with the previous Op"); + .catch(e => { + assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); done(); }); }); - it("fails when combining remove with add unique", (done) => { - const object = new Parse.Object("TestObject"); - object.set("strings", ["foo", "bar"]); + 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"); + object.remove('strings', 'bar'); + object.addUnique('strings', 'bar'); }) - .catch((e) => { - assert.equal( - e.message, - "Cannot merge AddUnique Op with the previous Op" - ); + .catch(e => { + assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); done(); }); }); - it("adds unique objects by id", (done) => { - const snowflake = new Parse.Object("Snowflake"); - const pocket = new Parse.Object("Pocket"); - snowflake.set("color", "white"); + 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"); + 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); + .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"); + const pocketQuery = new Parse.Query('Pocket'); + pocketQuery.include('snowflakes'); return pocketQuery.get(pocket.id); }) - .then((newPocket) => { + .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"); + 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) => { - const badEgg = new Parse.Object("Egg"); - badEgg.set("quality", "rotten"); - const goodEgg = new Parse.Object("Egg"); - goodEgg.set("quality", "good"); - const ostrichEgg = new Parse.Object("Egg"); - ostrichEgg.set("quality", "huge"); + it('removes objects by id', done => { + const badEgg = new Parse.Object('Egg'); + badEgg.set('quality', 'rotten'); + const goodEgg = new Parse.Object('Egg'); + goodEgg.set('quality', 'good'); + const ostrichEgg = new Parse.Object('Egg'); + ostrichEgg.set('quality', 'huge'); const eggs = [badEgg, goodEgg, ostrichEgg]; - const shelf = new Parse.Object("Shelf"); + const shelf = new Parse.Object('Shelf'); Parse.Object.saveAll(eggs) .then(() => { - shelf.set("eggs", eggs); - const badEggQuery = new Parse.Query("Egg"); + shelf.set('eggs', eggs); + const badEggQuery = new Parse.Query('Egg'); return badEggQuery.get(badEgg.id); }) - .then((badEggRef) => { + .then(badEggRef => { assert.notEqual(badEgg, badEggRef); - shelf.remove("eggs", badEggRef); - const fetchedEggs = shelf.get("eggs"); + 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"); + 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); + assert.equal(shelf.get('eggs').length, 2); done(); }); }); diff --git a/integration/test/DirtyTest.js b/integration/test/DirtyTest.js index ca06d9563..7574d6bf5 100644 --- a/integration/test/DirtyTest.js +++ b/integration/test/DirtyTest.js @@ -1,17 +1,17 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); -const Parent = Parse.Object.extend("Parent"); -const Child = Parse.Object.extend("Child"); +const TestObject = Parse.Object.extend('TestObject'); +const Parent = Parse.Object.extend('Parent'); +const Child = Parse.Object.extend('Child'); -describe("Dirty Objects", () => { - beforeEach((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Dirty Objects', () => { + beforeEach(done => { + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear() .then(() => { @@ -20,40 +20,40 @@ describe("Dirty Objects", () => { .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.set('scores', array); + assert.equal(object.get('scores').length, 1); object .save() .then(() => { array.push(2); - assert.equal(object.get("scores").length, 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); + .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.set('scores', [1]); object .save() .then(() => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - const array = o.get("scores"); + .then(o => { + const array = o.get('scores'); array.push(2); return o.save(); }) @@ -61,16 +61,16 @@ describe("Dirty Objects", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(o.get("scores").length, 2); + .then(o => { + assert.equal(o.get('scores').length, 2); done(); }); }); - it("tracks dirty objects", (done) => { + it('tracks dirty objects', done => { const dict = { player1: 1 }; const object = new TestObject(); - object.set("scoreMap", dict); + object.set('scoreMap', dict); object .save() .then(() => { @@ -81,24 +81,24 @@ describe("Dirty Objects", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(Object.keys(o.get("scoreMap")).length, 2); + .then(o => { + assert.equal(Object.keys(o.get('scoreMap')).length, 2); done(); }); }); - it("tracks dirty objects after fetch", (done) => { + it('tracks dirty objects after fetch', done => { const dict = { player1: 1 }; const object = new TestObject(); - object.set("scoreMap", dict); + 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"); + .then(o => { + const dictAgain = o.get('scoreMap'); dictAgain.player2 = 2; return o.save(); }) @@ -106,16 +106,16 @@ describe("Dirty Objects", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(Object.keys(o.get("scoreMap")).length, 2); + .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.set('location', geo); object .save() .then(() => { @@ -126,16 +126,16 @@ describe("Dirty Objects", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(o.get("location").latitude, 10); + .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); + object.set('location', geo); geo.latitude = 2.0; object .save() @@ -143,100 +143,100 @@ describe("Dirty Objects", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(o.get("location").latitude, 2); + .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); + child.set('ghostbuster', 'peter'); + parent.set('child', child); parent .save() .then(() => { - assert.equal(parent.get("child"), child); - assert.equal(child.get("ghostbuster"), "peter"); + 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) => { + .then(again => { parentAgain = again; newChild = new Child(); - newChild.set("ghostbuster", "ray"); - parentAgain.set("child", newChild); + 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"); + 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"); + 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"); + 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"); + .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"); + const newChildAgain = yetAgain.get('child'); assert.equal(newChildAgain.id, newChild.id); return newChildAgain.fetch(); }) - .then((c) => { - assert.equal(c.get("ghostbuster"), "ray"); + .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); + child.set('property', 'x'); + parent.set('children', [child]); + child.set('parent', parent); return Parse.Object.saveAll([parent, child]); }) - .then((results) => { + .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" }) + .save({ foo: 'bar' }) .then(() => { assert.equal(object.dirty(), false); - object.unset("foo"); + object.unset('foo'); assert.equal(object.dirty(), true); return object.save(); diff --git a/integration/test/IdempotencyTest.js b/integration/test/IdempotencyTest.js index f2cd99629..0ce710165 100644 --- a/integration/test/IdempotencyTest.js +++ b/integration/test/IdempotencyTest.js @@ -1,9 +1,9 @@ -"use strict"; +'use strict'; -const clear = require("./clear"); -const Parse = require("../../node"); +const clear = require('./clear'); +const Parse = require('../../node'); -const Item = Parse.Object.extend("IdempotencyItem"); +const Item = Parse.Object.extend('IdempotencyItem'); const RESTController = Parse.CoreManager.getRESTController(); const XHR = RESTController._getXHR(); @@ -12,7 +12,7 @@ function DuplicateXHR(requestId) { const xhr = new XHR(); const send = xhr.send; xhr.send = function () { - this.setRequestHeader("X-Parse-Request-Id", requestId); + this.setRequestHeader('X-Parse-Request-Id', requestId); send.apply(this, arguments); }; return xhr; @@ -20,10 +20,10 @@ function DuplicateXHR(requestId) { return XHRWrapper; } -describe("Idempotency", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Idempotency', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); RESTController._setXHR(XHR); clear().then(() => { @@ -31,52 +31,48 @@ 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"); + 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' + ); const query = new Parse.Query(Item); const results = await query.find(); expect(results.length).toBe(1); }); - it("handle duplicate job request", async () => { - 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"); + it('handle duplicate job request', async () => { + 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' + ); const jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - expect(jobStatus.get("status")).toBe("succeeded"); - expect(jobStatus.get("params").startedBy).toBe("Monty Python"); + expect(jobStatus.get('status')).toBe('succeeded'); + expect(jobStatus.get('params').startedBy).toBe('Monty Python'); }); - it("handle duplicate POST / PUT request", async () => { - RESTController._setXHR(DuplicateXHR("1234")); - const testObject = new Parse.Object("IdempotentTest"); + it('handle duplicate POST / PUT request', async () => { + RESTController._setXHR(DuplicateXHR('1234')); + const testObject = new Parse.Object('IdempotentTest'); await testObject.save(); - await expectAsync(testObject.save()).toBeRejectedWithError( - "Duplicate request" - ); + await expectAsync(testObject.save()).toBeRejectedWithError('Duplicate request'); - RESTController._setXHR(DuplicateXHR("5678")); - testObject.set("foo", "bar"); + RESTController._setXHR(DuplicateXHR('5678')); + testObject.set('foo', 'bar'); await testObject.save(); - await expectAsync(testObject.save()).toBeRejectedWithError( - "Duplicate request" - ); + await expectAsync(testObject.save()).toBeRejectedWithError('Duplicate request'); - const query = new Parse.Query("IdempotentTest"); + const query = new Parse.Query('IdempotentTest'); const results = await query.find(); expect(results.length).toBe(1); - expect(results[0].get("foo")).toBe("bar"); + expect(results[0].get('foo')).toBe('bar'); }); }); diff --git a/integration/test/IncrementTest.js b/integration/test/IncrementTest.js index c3cc5b1ae..bb3fa612a 100644 --- a/integration/test/IncrementTest.js +++ b/integration/test/IncrementTest.js @@ -1,15 +1,15 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Increment", () => { - beforeEach((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Increment', () => { + beforeEach(done => { + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear() .then(() => { @@ -18,101 +18,101 @@ describe("Increment", () => { .catch(done.fail); }); - it("can increment a field", (done) => { + it('can increment a field', done => { const object = new TestObject(); - object.set("score", 1); + object.set('score', 1); object .save() .then(() => { - object.increment("score"); + 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); + .then(o => { + assert.equal(o.get('score'), 2); done(); }); }); - it("can increment on a fresh object", () => { + it('can increment on a fresh object', () => { const object = new TestObject(); - object.set("score", 1); - object.increment("score"); - assert.equal(object.get("score"), 2); + object.set('score', 1); + object.increment('score'); + 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.set('score', 1); object .save() .then(() => { - object.increment("score", 10); + 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); + .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.set('score', 1); object .save() .then(() => { - object.increment("score", -1); + 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); + .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.set('score', 1.0); object .save() .then(() => { - object.increment("score", 1.5); + 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); + .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.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"); + .then(o => { + object.increment('score'); + o.increment('score'); return o.save(); }) .then(() => { @@ -122,131 +122,131 @@ describe("Increment", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(o.get("score"), 3); + .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.set('score', 1); object .save() .then(() => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { + .then(o => { objectAgain = o; - assert.equal(o.get("score"), 1); - object.increment("score"); - assert.equal(object.get("score"), 2); + 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"); + assert.equal(object.get('score'), 2); + objectAgain.increment('score'); return objectAgain.save(); }) .then(() => { - assert.equal(objectAgain.get("score"), 3); + 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.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"); + .then(o => { + o.increment('score'); + o.set('name', 'parse'); return o.save(); }) .then(() => { - object.increment("score"); + 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); + .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.set('not_score', 'foo'); object.save().then(() => { try { - object.increment("not_score"); + object.increment('not_score'); } catch (e) { done(); } }); }); - 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.set('score', 1); object .save() .then(() => { - object.unset("score"); - object.increment("score"); - assert.equal(object.get("score"), 1); + 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); + .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.increment('score'); object .save() .then(() => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - o.get("score", 1); + .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"); + object.increment('score'); const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { + .then(o => { objectAgain = o; - o.increment("score"); + o.increment('score'); return object.save(); }) .then(() => { @@ -256,19 +256,19 @@ describe("Increment", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((o) => { - assert.equal(o.get("score"), 2); + .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.increment('numeric'); object .save() .then(() => { - object.set("numeric", "x"); + object.set('numeric', 'x'); return object.save(); }) .catch(() => { diff --git a/integration/test/ParseACLTest.js b/integration/test/ParseACLTest.js index 0a76005cf..be8a2b9fe 100644 --- a/integration/test/ParseACLTest.js +++ b/integration/test/ParseACLTest.js @@ -1,15 +1,15 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Parse.ACL", () => { - beforeEach((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse.ACL', () => { + beforeEach(done => { + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); Parse.User.enableUnsafeCurrentUser(); clear() @@ -26,16 +26,16 @@ describe("Parse.ACL", () => { .catch(done.fail); }); - it("acl must be valid", () => { + it('acl must be valid', () => { const user = new Parse.User(); assert.equal(user.setACL(`Ceci n'est pas un ACL.`), false); }); - it("can refresh object with acl", async () => { + it('can refresh object with acl', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "alice"); - user.set("password", "wonderland"); + user.set('username', 'alice'); + user.set('password', 'wonderland'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -45,11 +45,11 @@ describe("Parse.ACL", () => { assert(o); }); - it("disables public get access", async () => { + it('disables public get access', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "getter"); - user.set("password", "secret"); + user.set('username', 'getter'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -70,11 +70,11 @@ describe("Parse.ACL", () => { } }); - it("disables public find access", async () => { + it('disables public find access', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "finder"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'finder'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -87,16 +87,16 @@ describe("Parse.ACL", () => { assert.equal(object.getACL().getPublicWriteAccess(), false); await Parse.User.logOut(); - const query = new Parse.Query("UniqueObject"); + const query = new Parse.Query('UniqueObject'); const o = await query.find(); assert.equal(o.length, 0); }); - it("disables public update access", async () => { + it('disables public update access', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "updater"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'updater'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -110,7 +110,7 @@ describe("Parse.ACL", () => { await Parse.User.logOut(); - object.set("score", 10); + object.set('score', 10); try { await object.save(); } catch (e) { @@ -118,11 +118,11 @@ describe("Parse.ACL", () => { } }); - it("disables public delete access", async () => { + it('disables public delete access', async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set("username", "deleter"); - user.set("password", "secret"); + user.set('username', 'deleter'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -143,11 +143,11 @@ describe("Parse.ACL", () => { } }); - it("allows logged in get", async () => { + it('allows logged in get', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "getter2"); - user.set("password", "secret"); + user.set('username', 'getter2'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -158,40 +158,40 @@ describe("Parse.ACL", () => { assert(o); }); - it("allows logged in find", async () => { + it('allows logged in find', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "finder2"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'finder2'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); await object.save(); - const o = await new Parse.Query("UniqueObject").find(); + const o = await new Parse.Query('UniqueObject').find(); assert(o.length > 0); }); - it("allows logged in update", async () => { + it('allows logged in update', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "updater2"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'updater2'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); await object.save(); - object.set("score", 10); + object.set('score', 10); await object.save(); - assert.equal(object.get("score"), 10); + assert.equal(object.get('score'), 10); }); - it("allows logged in delete", async () => { + it('allows logged in delete', async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set("username", "deleter2"); - user.set("password", "secret"); + user.set('username', 'deleter2'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); @@ -201,11 +201,11 @@ describe("Parse.ACL", () => { await object.destroy(); }); - it("enables get with public read", async () => { + it('enables get with public read', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "getter3"); - user.set("password", "secret"); + user.set('username', 'getter3'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -219,11 +219,11 @@ describe("Parse.ACL", () => { assert(o); }); - it("enables find with public read", async () => { + it('enables find with public read', async () => { const user = new Parse.User(); - const object = new Parse.Object("AlsoUniqueObject"); - user.set("username", "finder3"); - user.set("password", "secret"); + const object = new Parse.Object('AlsoUniqueObject'); + user.set('username', 'finder3'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -233,16 +233,16 @@ describe("Parse.ACL", () => { await object.save(); Parse.User.logOut(); - const o = await new Parse.Query("AlsoUniqueObject").find(); + const o = await new Parse.Query('AlsoUniqueObject').find(); assert(o.length > 0); }); - it("does not enable update with public read", async () => { + it('does not enable update with public read', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "updater3"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'updater3'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -252,7 +252,7 @@ describe("Parse.ACL", () => { await object.save(); Parse.User.logOut(); - object.set("score", 10); + object.set('score', 10); try { await object.save(); } catch (e) { @@ -260,11 +260,11 @@ describe("Parse.ACL", () => { } }); - it("does not enable delete with public read", async () => { + it('does not enable delete with public read', async () => { const user = new Parse.User(); const object = new Parse.Object(TestObject); - user.set("username", "deleter3"); - user.set("password", "secret"); + user.set('username', 'deleter3'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -281,11 +281,11 @@ describe("Parse.ACL", () => { } }); - it("does not enable get with public write", async () => { + it('does not enable get with public write', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "getter4"); - user.set("password", "secret"); + user.set('username', 'getter4'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -302,11 +302,11 @@ describe("Parse.ACL", () => { } }); - it("does not enable find with public write", async () => { + it('does not enable find with public write', async () => { const user = new Parse.User(); - const object = new Parse.Object("AnotherUniqueObject"); - user.set("username", "finder4"); - user.set("password", "secret"); + const object = new Parse.Object('AnotherUniqueObject'); + user.set('username', 'finder4'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -316,15 +316,15 @@ describe("Parse.ACL", () => { await object.save(); await Parse.User.logOut(); - const o = await new Parse.Query("AnotherUniqueObject").find(); + const o = await new Parse.Query('AnotherUniqueObject').find(); assert.equal(o.length, 0); }); - it("enables update with public read", async () => { + it('enables update with public read', async () => { const user = new Parse.User(); - const object = new Parse.Object("UniqueObject"); - user.set("username", "updater4"); - user.set("password", "secret"); + const object = new Parse.Object('UniqueObject'); + user.set('username', 'updater4'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -334,15 +334,15 @@ describe("Parse.ACL", () => { await object.save(); await Parse.User.logOut(); - object.set("score", 10); + object.set('score', 10); await object.save(); }); - it("enables delete with public read", async () => { + it('enables delete with public read', async () => { const user = new Parse.User(); const object = new TestObject(); - user.set("username", "deleter4"); - user.set("password", "secret"); + user.set('username', 'deleter4'); + user.set('password', 'secret'); await user.signUp(); const acl = new Parse.ACL(user); object.setACL(acl); @@ -355,12 +355,12 @@ describe("Parse.ACL", () => { await object.destroy(); }); - it("can grant get access to another user", async () => { + it('can grant get access to another user', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp("aaa", "password"); + const user1 = await Parse.User.signUp('aaa', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("bbb", "password"); + const user2 = await Parse.User.signUp('bbb', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -368,19 +368,19 @@ describe("Parse.ACL", () => { object.setACL(acl); await object.save(); - await Parse.User.logIn("aaa", "password"); + await Parse.User.logIn('aaa', 'password'); const query = new Parse.Query(TestObject); const o = await query.get(object.id); assert.equal(o.id, object.id); }); - it("can grant find access to another user", async () => { - const object = new Parse.Object("ThatOneObject"); - const user1 = await Parse.User.signUp("ccc", "password"); + it('can grant find access to another user', async () => { + const object = new Parse.Object('ThatOneObject'); + const user1 = await Parse.User.signUp('ccc', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("ddd", "password"); + const user2 = await Parse.User.signUp('ddd', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -388,20 +388,20 @@ describe("Parse.ACL", () => { object.setACL(acl); await object.save(); - await Parse.User.logIn("ccc", "password"); + await Parse.User.logIn('ccc', 'password'); - const query = new Parse.Query("ThatOneObject"); + const query = new Parse.Query('ThatOneObject'); const o = await query.find(); assert(o.length > 0); }); - it("can grant update access to another user", async () => { + it('can grant update access to another user', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp("eee", "password"); + const user1 = await Parse.User.signUp('eee', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("fff", "password"); + const user2 = await Parse.User.signUp('fff', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -409,19 +409,19 @@ describe("Parse.ACL", () => { object.setACL(acl); await object.save(); - await Parse.User.logIn("eee", "password"); + await Parse.User.logIn('eee', 'password'); - object.set("score", 10); + object.set('score', 10); const o = await object.save(); - assert.equal(o.get("score"), 10); + assert.equal(o.get('score'), 10); }); - it("can grant delete access to another user", async () => { + 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"); + const user2 = await Parse.User.signUp('hhh', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -429,16 +429,16 @@ describe("Parse.ACL", () => { object.setACL(acl); await object.save(); - await Parse.User.logIn("ggg", "password"); + await Parse.User.logIn('ggg', 'password'); await object.destroy(); }); - it("does not grant public get access with another user acl", async () => { + it('does not grant public get access with another user acl', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp("iii", "password"); + const user1 = await Parse.User.signUp('iii', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("jjj", "password"); + const user2 = await Parse.User.signUp('jjj', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -456,12 +456,12 @@ describe("Parse.ACL", () => { } }); - it("does not grant public find access with another user acl", async () => { - const object = new Parse.Object("ThatOneObject"); - const user1 = await Parse.User.signUp("kkk", "password"); + it('does not grant public find access with another user acl', async () => { + const object = new Parse.Object('ThatOneObject'); + const user1 = await Parse.User.signUp('kkk', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("lll", "password"); + const user2 = await Parse.User.signUp('lll', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -471,19 +471,19 @@ describe("Parse.ACL", () => { await Parse.User.logOut(); - const query = new Parse.Query("ThatOneObject"); + const query = new Parse.Query('ThatOneObject'); const o = await query.find(); assert.equal(o.length, 0); }); - it("does not grant public update access with another user acl", async () => { + it('does not grant public update access with another user acl', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp("mmm", "password"); + const user1 = await Parse.User.signUp('mmm', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("nnn", "password"); + const user2 = await Parse.User.signUp('nnn', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); acl.setReadAccess(user1, true); @@ -492,7 +492,7 @@ describe("Parse.ACL", () => { await Parse.User.logOut(); - object.set("score", 10); + object.set('score', 10); try { await object.save(); } catch (e) { @@ -500,13 +500,13 @@ describe("Parse.ACL", () => { } }); - it("does not grant public destroy access with another user acl", async () => { + it('does not grant public destroy access with another user acl', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp("ooo", "password"); + const user1 = await Parse.User.signUp('ooo', 'password'); await Parse.User.logOut(); - const user2 = await Parse.User.signUp("ppp", "password"); + const user2 = await Parse.User.signUp('ppp', 'password'); const acl = new Parse.ACL(user2); acl.setWriteAccess(user1, true); @@ -523,32 +523,32 @@ describe("Parse.ACL", () => { } }); - it("allows access with an empty acl", async () => { - await Parse.User.signUp("tdurden", "mayhem", { + 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"); - assert.equal(user.get("foo"), "bar"); + const user = await Parse.User.logIn('tdurden', 'mayhem'); + assert.equal(user.get('foo'), 'bar'); }); - it("fetches the ACL with included pointers", async () => { - const obj1 = new Parse.Object("TestClass1"); - const obj2 = new Parse.Object("TestClass2"); + it('fetches the ACL with included pointers', async () => { + const obj1 = new Parse.Object('TestClass1'); + const obj2 = new Parse.Object('TestClass2'); const acl = new Parse.ACL(); acl.setPublicReadAccess(true); - obj2.set("ACL", acl); - obj1.set("other", obj2); + obj2.set('ACL', acl); + obj1.set('other', obj2); await obj1.save(); - let query = new Parse.Query("TestClass1"); + let query = new Parse.Query('TestClass1'); const obj1again = await query.first(); assert(obj1again); - assert(!obj1again.get("other").get("ACL")); - query = new Parse.Query("TestClass1"); - query.include("other"); + assert(!obj1again.get('other').get('ACL')); + query = new Parse.Query('TestClass1'); + query.include('other'); const obj1withInclude = await query.first(); - assert(obj1withInclude.get("other").get("ACL")); + assert(obj1withInclude.get('other').get('ACL')); }); }); diff --git a/integration/test/ParseCloudTest.js b/integration/test/ParseCloudTest.js index c6248576b..7ddedf3c9 100644 --- a/integration/test/ParseCloudTest.js +++ b/integration/test/ParseCloudTest.js @@ -1,14 +1,14 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); -const sleep = require("./sleep"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); +const sleep = require('./sleep'); -describe("Parse Cloud", () => { - beforeAll((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Cloud', () => { + beforeAll(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then( () => { @@ -20,28 +20,28 @@ describe("Parse Cloud", () => { ); }); - it("run function", (done) => { - const params = { key1: "value2", key2: "value1" }; - Parse.Cloud.run("bar", params) - .then((result) => { - assert.equal("Foo", result); + 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); }); - it("run function with user", (done) => { - const params = { key1: "value2", key2: "value1" }; + it('run function with user', done => { + const params = { key1: 'value2', key2: 'value1' }; const user = new Parse.User(); - user.setUsername("someuser"); - user.setPassword("somepassword"); + user.setUsername('someuser'); + user.setPassword('somepassword'); user .signUp() .then(() => { - return Parse.Cloud.run("bar", params); + return Parse.Cloud.run('bar', params); }) - .then((resp) => { - assert.equal("Foo", resp); + .then(resp => { + assert.equal('Foo', resp); return user.destroy({ useMasterKey: true }); }) .then(() => { @@ -50,114 +50,114 @@ describe("Parse Cloud", () => { .catch(done.fail); }); - it("run function failed", (done) => { - const params = { key1: "value1", key2: "value2" }; - Parse.Cloud.run("bar", params) + it('run function failed', done => { + const params = { key1: 'value1', key2: 'value2' }; + Parse.Cloud.run('bar', params) .then(done.fail) - .catch((error) => { + .catch(error => { assert.equal(error.code, Parse.Error.SCRIPT_FAILED); done(); }); }); - it("run function name fail", (done) => { - const params = { key1: "value1" }; - Parse.Cloud.run("unknown_function", params) + it('run function name fail', done => { + const params = { key1: 'value1' }; + Parse.Cloud.run('unknown_function', params) .then(done.fail) - .catch((error) => { + .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) + Parse.Cloud.run('unknown_function', params) .then(null) - .catch((error) => { + .catch(error => { assert.equal(error.message, 'Invalid function: "unknown_function"'); done(); }); }); - it("run function with object params fail", (done) => { - const object = new Parse.Object("TestClass"); + it('run function with object params fail', done => { + const object = new Parse.Object('TestClass'); const params = { key1: object }; try { - Parse.Cloud.run("bar", params); + Parse.Cloud.run('bar', params); } catch (e) { - assert.equal(e, "Error: Parse Objects not allowed here"); + assert.equal(e, 'Error: Parse Objects not allowed here'); done(); } }); - 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) => { - const params = { startedBy: "Monty Python" }; - Parse.Cloud.startJob("CloudJob1", params) - .then((jobStatusId) => { + 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"); + .then(jobStatus => { + assert.equal(jobStatus.get('status'), 'succeeded'); + assert.equal(jobStatus.get('params').startedBy, 'Monty Python'); done(); }); }); - it("run long job", async () => { - const jobStatusId = await Parse.Cloud.startJob("CloudJob2"); + it('run long job', async () => { + const jobStatusId = await Parse.Cloud.startJob('CloudJob2'); let jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - assert.equal(jobStatus.get("status"), "running"); + assert.equal(jobStatus.get('status'), 'running'); await sleep(2000); jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); - assert.equal(jobStatus.get("status"), "succeeded"); + assert.equal(jobStatus.get('status'), 'succeeded'); }); - it("run bad job", (done) => { - Parse.Cloud.startJob("bad_job") + it('run bad job', done => { + Parse.Cloud.startJob('bad_job') .then(null) - .catch((error) => { + .catch(error => { assert.equal(error.code, Parse.Error.SCRIPT_FAILED); - assert.equal(error.message, "Invalid job."); + assert.equal(error.message, 'Invalid job.'); done(); }); }); - it("run failing job", (done) => { - Parse.Cloud.startJob("CloudJobFailing") - .then((jobStatusId) => { + 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"); + .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") + it('invalid job status id', done => { + Parse.Cloud.getJobStatus('not-a-real-id') .then(null) - .catch((error) => { - assert.equal(error.message, "Object not found."); + .catch(error => { + assert.equal(error.message, 'Object not found.'); done(); }); }); diff --git a/integration/test/ParseConfigTest.js b/integration/test/ParseConfigTest.js index 2a59e9e35..857c09759 100644 --- a/integration/test/ParseConfigTest.js +++ b/integration/test/ParseConfigTest.js @@ -1,57 +1,54 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +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) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Config', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it("can create a config", async () => { + it('can create a config', async () => { const config = await testConfig(); assert.notStrictEqual(config, undefined); - assert.strictEqual(config.get("string"), "s"); - assert.strictEqual(config.get("internal"), "i"); - assert.strictEqual(config.get("number"), 12); + assert.strictEqual(config.get('string'), 's'); + assert.strictEqual(config.get('internal'), 'i'); + assert.strictEqual(config.get('number'), 12); }); - it("can get a config", async () => { + it('can get a config', async () => { await testConfig(); const config = await Parse.Config.get(); assert.notStrictEqual(config, undefined); - assert.strictEqual(config.get("string"), "s"); - assert.strictEqual(config.get("number"), 12); + assert.strictEqual(config.get('string'), 's'); + assert.strictEqual(config.get('number'), 12); }); - it("can get internal config parameter with masterkey", async () => { + it('can get internal config parameter with masterkey', async () => { await testConfig(); const config = await Parse.Config.get({ useMasterKey: true }); - assert.equal(config.get("internal"), "i"); - assert.equal(config.get("string"), "s"); + assert.equal(config.get('internal'), 'i'); + assert.equal(config.get('string'), 's'); }); - it("cannot get internal config parameter without masterkey", async () => { + it('cannot get internal config parameter without masterkey', async () => { await testConfig(); const config = await Parse.Config.get(); - assert.equal(config.get("internal"), undefined); - assert.equal(config.get("string"), "s"); + assert.equal(config.get('internal'), undefined); + assert.equal(config.get('string'), 's'); }); }); diff --git a/integration/test/ParseFileTest.js b/integration/test/ParseFileTest.js index b6ba6d1aa..3e974d15b 100644 --- a/integration/test/ParseFileTest.js +++ b/integration/test/ParseFileTest.js @@ -1,49 +1,49 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -describe("Parse.File", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse.File', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(done).catch(done.fail); }); - it("can save file with uri", async () => { + 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 file1 = new Parse.File("parse-server-logo", { uri: 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(); - const object = new Parse.Object("TestObject"); - object.set("file1", file1); + const object = new Parse.Object('TestObject'); + object.set('file1', file1); await object.save(); - const query = new Parse.Query("TestObject"); + const query = new Parse.Query('TestObject'); let result = await query.get(object.id); - assert.equal(file1.name(), result.get("file1").name()); - assert.equal(file1.url(), result.get("file1").url()); + assert.equal(file1.name(), result.get('file1').name()); + assert.equal(file1.url(), result.get('file1').url()); // Try http - const file2 = new Parse.File("parse-server-logo", { uri: file1.url() }); + const file2 = new Parse.File('parse-server-logo', { uri: file1.url() }); await file2.save(); - object.set("file2", file2); + object.set('file2', file2); await object.save(); result = await query.get(object.id); - assert.equal(file2.url(), result.get("file2").url()); + assert.equal(file2.url(), result.get('file2').url()); }); - it("can cancel save file with uri", async () => { + 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 file = new Parse.File("parse-server-logo", { uri: 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); assert.equal(file.url(), undefined); @@ -51,55 +51,55 @@ describe("Parse.File", () => { file.cancel(); }); - it("can not get data from unsaved file", async () => { - const file = new Parse.File("parse-server-logo", [61, 170, 236, 120]); + it('can not get data from unsaved file', async () => { + const file = new Parse.File('parse-server-logo', [61, 170, 236, 120]); file._data = null; try { await file.getData(); } catch (e) { - assert.equal(e.message, "Cannot retrieve data for unsaved ParseFile."); + assert.equal(e.message, 'Cannot retrieve data for unsaved ParseFile.'); } }); - it("can get file data from byte array", async () => { - const file = new Parse.File("parse-server-logo", [61, 170, 236, 120]); + it('can get file data from byte array', async () => { + const file = new Parse.File('parse-server-logo', [61, 170, 236, 120]); let data = await file.getData(); - assert.equal(data, "ParseA=="); + assert.equal(data, 'ParseA=='); file._data = null; await file.save(); assert.equal(file._data, null); data = await file.getData(); - assert.equal(data, "ParseA=="); + assert.equal(data, 'ParseA=='); }); - it("can get file data from base64", async () => { - const file = new Parse.File("parse-server-logo", { base64: "ParseA==" }); + it('can get file data from base64', async () => { + const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); let data = await file.getData(); - assert.equal(data, "ParseA=="); + assert.equal(data, 'ParseA=='); file._data = null; await file.save(); assert.equal(file._data, null); data = await file.getData(); - assert.equal(data, "ParseA=="); + 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==", + it('can get file data from full base64', async () => { + const file = new Parse.File('parse-server-logo', { + base64: 'data:image/jpeg;base64,ParseA==', }); let data = await file.getData(); - assert.equal(data, "ParseA=="); + assert.equal(data, 'ParseA=='); file._data = null; await file.save(); assert.equal(file._data, null); data = await file.getData(); - assert.equal(data, "ParseA=="); + assert.equal(data, 'ParseA=='); }); - it("can delete file", async () => { + it('can delete file', async () => { 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 }); + '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(); @@ -109,10 +109,10 @@ describe("Parse.File", () => { assert.notEqual(data, deletedData); }); - it("can handle delete file error", async () => { + it('can handle delete file error', async () => { 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 }); + '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(); assert.equal(false, true); diff --git a/integration/test/ParseGeoBoxTest.js b/integration/test/ParseGeoBoxTest.js index 9011f070e..377bc757d 100644 --- a/integration/test/ParseGeoBoxTest.js +++ b/integration/test/ParseGeoBoxTest.js @@ -1,121 +1,121 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); const southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398); const northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962); -describe("Geo Box", () => { +describe('Geo Box', () => { beforeAll(() => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); 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); - caltrainStation.set("name", "caltrain"); + const caltrainStation = new Parse.Object('Location'); + caltrainStation.set('location', caltrainStationLocation); + caltrainStation.set('name', 'caltrain'); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object("Location"); - santaClara.set("location", santaClaraLocation); - santaClara.set("name", "santa clara"); + const santaClara = new Parse.Object('Location'); + 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); + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); return query.find(); }) - .then((objectsInSF) => { + .then(objectsInSF => { assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get("name"), "caltrain"); + 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); - caltrainStation.set("name", "caltrain"); + const caltrainStation = new Parse.Object('Location'); + caltrainStation.set('location', caltrainStationLocation); + caltrainStation.set('name', 'caltrain'); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object("Location"); - santaClara.set("location", santaClaraLocation); - santaClara.set("name", "santa clara"); + const santaClara = new Parse.Object('Location'); + santaClara.set('location', santaClaraLocation); + santaClara.set('name', 'santa clara'); 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); + const query = new Parse.Query('Location'); + query.withinGeoBox('location', northeastOfSF, southwestOfSF); return query.find(); }) - .then((objectsInSF) => { + .then(objectsInSF => { assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get("name"), "caltrain"); + 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); - caltrainStation.set("name", "caltrain"); + const caltrainStation = new Parse.Object('Location'); + caltrainStation.set('location', caltrainStationLocation); + caltrainStation.set('name', 'caltrain'); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object("Location"); - santaClara.set("location", santaClaraLocation); - santaClara.set("name", "santa clara"); + const santaClara = new Parse.Object('Location'); + 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); + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); return query.find(); }) - .then((objectsInSF) => { + .then(objectsInSF => { assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get("name"), "caltrain"); + 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); - caltrainStation.set("name", "caltrain"); + const caltrainStation = new Parse.Object('Location'); + caltrainStation.set('location', caltrainStationLocation); + caltrainStation.set('name', 'caltrain'); const santaClaraLocation = new Parse.GeoPoint(37.325635, -121.945753); - const santaClara = new Parse.Object("Location"); - santaClara.set("location", santaClaraLocation); - santaClara.set("name", "santa clara"); + const santaClara = new Parse.Object('Location'); + 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); + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); return query.find(); }) - .then((objectsInSF) => { + .then(objectsInSF => { assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get("name"), "caltrain"); + assert.equal(objectsInSF[0].get('name'), 'caltrain'); done(); }) .catch(done.fail); diff --git a/integration/test/ParseGeoPointTest.js b/integration/test/ParseGeoPointTest.js index ea5115aa7..ab194fbf4 100644 --- a/integration/test/ParseGeoPointTest.js +++ b/integration/test/ParseGeoPointTest.js @@ -1,32 +1,32 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); -const TestPoint = Parse.Object.extend("TestPoint"); -const Container = Parse.Object.extend("Container"); +const TestObject = Parse.Object.extend('TestObject'); +const TestPoint = Parse.Object.extend('TestPoint'); +const Container = Parse.Object.extend('Container'); -describe("Geo Point", () => { - beforeAll((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); - Parse.CoreManager.set("REQUEST_ATTEMPT_LIMIT", 1); +describe('Geo Point', () => { + 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.5)); - sacramento.set("name", "Sacramento"); + 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"); + 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"); + sf.set('location', new Parse.GeoPoint(37.75, -122.68)); + sf.set('name', 'San Francisco'); return Parse.Object.saveAll([sacramento, honolulu, sf]); }) @@ -43,30 +43,30 @@ describe("Geo Point", () => { ); }); - 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("name", "Ferndale"); + 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); + .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.set('locationOne', point); + obj.set('locationTwo', point); obj .save() .then(done.fail) @@ -75,381 +75,381 @@ describe("Geo Point", () => { }); }); - 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(); const point = new Parse.GeoPoint(i * 4 - 12, i * 3.2 - 11); - obj.set("location", point); - obj.set("construct", "line"); - obj.set("seq", i); + obj.set('location', point); + obj.set('construct', 'line'); + 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); + query.equalTo('construct', 'line'); + query.withinMiles('location', point, 10000); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 10); - assert.equal(results[0].get("seq"), 9); - assert.equal(results[3].get("seq"), 6); + 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(); const point = new Parse.GeoPoint(i * 4 - 12, i * 3.2 - 11); - obj.set("location", point); - obj.set("construct", "line_unsorted"); - obj.set("seq", i); + obj.set('location', point); + obj.set('construct', 'line_unsorted'); + 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); + query.equalTo('construct', 'line_unsorted'); + query.withinMiles('location', point, 10000, true); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 10); - assert.equal(results[0].get("seq"), 9); - assert.equal(results[3].get("seq"), 6); + 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("index", i); + obj.set('location', point); + 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); + query.equalTo('construct', 'large_dist'); + query.withinRadians('location', point, 3.14); return query.find(); }) - .then((results) => { + .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("index", i); + obj.set('location', point); + 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); + query.equalTo('construct', 'medium_dist'); + query.withinRadians('location', point, 3.14 * 0.5); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("index"), 0); - assert.equal(results[1].get("index"), 1); + 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("index", i); + obj.set('location', point); + 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); + query.equalTo('construct', 'small_dist'); + query.withinRadians('location', point, 3.14 * 0.25); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("index"), 0); + 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.withinKilometers('location', sfo, 4000.0); + 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.withinKilometers('location', sfo, 3700.0); + query.find().then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "San Francisco"); - assert.equal(results[1].get("name"), "Sacramento"); + assert.equal(results[0].get('name'), 'San Francisco'); + assert.equal(results[1].get('name'), 'Sacramento'); done(); }); }); - 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.withinKilometers('location', sfo, 100.0); + query.find().then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "San Francisco"); + 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.withinKilometers('location', sfo, 10.0); + 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.withinMiles('location', sfo, 2500.0); + 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.withinMiles('location', sfo, 2200.0); + query.find().then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "San Francisco"); - assert.equal(results[1].get("name"), "Sacramento"); + assert.equal(results[0].get('name'), 'San Francisco'); + assert.equal(results[1].get('name'), 'Sacramento'); done(); }); }); - 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.withinMiles('location', sfo, 75.0); + query.find().then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "San Francisco"); + 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.withinMiles('location', sfo, 10.0); + 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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set("location", point); - obj.set("construct", "large_dist_unsorted"); - obj.set("index", i); + obj.set('location', point); + obj.set('construct', 'large_dist_unsorted'); + 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); + query.equalTo('construct', 'large_dist_unsorted'); + query.withinRadians('location', point, 3.14, false); return query.find(); }) - .then((results) => { + .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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set("location", point); - obj.set("construct", "medium_dist_unsorted"); - obj.set("index", i); + obj.set('location', point); + obj.set('construct', 'medium_dist_unsorted'); + 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); + query.equalTo('construct', 'medium_dist_unsorted'); + query.withinRadians('location', point, 3.14 * 0.5, false); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("index"), 0); - assert.equal(results[1].get("index"), 1); + 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(); const point = new Parse.GeoPoint(0, i * 45); - obj.set("location", point); - obj.set("construct", "small_dist_unsorted"); - obj.set("index", i); + obj.set('location', point); + obj.set('construct', 'small_dist_unsorted'); + 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); + query.equalTo('construct', 'small_dist_unsorted'); + query.withinRadians('location', point, 3.14 * 0.25, false); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("index"), 0); + 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.withinKilometers('location', sfo, 4000.0, false); + 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.withinKilometers('location', sfo, 3700.0, false); + query.find().then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "San Francisco"); - assert.equal(results[1].get("name"), "Sacramento"); + assert.equal(results[0].get('name'), 'San Francisco'); + assert.equal(results[1].get('name'), 'Sacramento'); done(); }); }); - 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.withinKilometers('location', sfo, 100.0, false); + query.find().then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "San Francisco"); + 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.withinKilometers('location', sfo, 10.0, false); + 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.withinMiles('location', sfo, 2500.0, false); + 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.withinMiles('location', sfo, 2200.0, false); + query.find().then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "San Francisco"); - assert.equal(results[1].get("name"), "Sacramento"); + assert.equal(results[0].get('name'), 'San Francisco'); + assert.equal(results[1].get('name'), 'Sacramento'); done(); }); }); - 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.withinMiles('location', sfo, 75.0, false); + query.find().then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "San Francisco"); + 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.withinMiles('location', sfo, 10.0, false); + 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.9), @@ -457,14 +457,14 @@ describe("Geo Point", () => { new Parse.GeoPoint(37.68, -122.33), ]; const query = new Parse.Query(TestPoint); - query.withinPolygon("location", points); - query.find().then((results) => { + query.withinPolygon('location', points); + 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.5), new Parse.GeoPoint(37.75, -157.93), @@ -472,44 +472,44 @@ describe("Geo Point", () => { new Parse.GeoPoint(38.52, -121.5), ]; const query = new Parse.Query(TestPoint); - query.withinPolygon("location", points); - query.find().then((results) => { + query.withinPolygon('location', points); + 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.withinPolygon('location', 1234); + 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.withinPolygon('location', [1234]); + query.find().catch(err => { assert.equal(err.code, Parse.Error.INVALID_JSON); done(); }); }); xit( - "minimum 3 points withinPolygon", + 'minimum 3 points withinPolygon', function (done) { const query = new Parse.Query(TestPoint); - query.withinPolygon("location", []); + query.withinPolygon('location', []); query .find() - .then(done.fail, (err) => { + .then(done.fail, err => { assert.equal(err.code, Parse.Error.INVALID_JSON); done(); }) .catch(done.fail); }, - "Test passes locally but not on CI" + 'Test passes locally but not on CI' ); }); diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index 28248de82..89e33a0b0 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -1,169 +1,169 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); -const sleep = require("./sleep"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); +const sleep = require('./sleep'); -const TestObject = Parse.Object.extend("TestObject"); -const DiffObject = Parse.Object.extend("DiffObject"); +const TestObject = Parse.Object.extend('TestObject'); +const DiffObject = Parse.Object.extend('DiffObject'); -describe("Parse LiveQuery", () => { - beforeEach((done) => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse LiveQuery', () => { + beforeEach(done => { + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.User.enableUnsafeCurrentUser(); Parse.Storage._clear(); 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(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + query.equalTo('objectId', object.id); const subscription = await query.subscribe(); - subscription.on("update", (object, original, response) => { - assert.equal(object.get("foo"), "bar"); + subscription.on('update', (object, original, response) => { + assert.equal(object.get('foo'), 'bar'); assert.equal(response.installationId, installationId); done(); }); - object.set({ foo: "bar" }); + 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(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + query.equalTo('objectId', object.id); const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); if (client.shouldOpen()) { client.open(); } const subscription = client.subscribe(query); - subscription.on("update", (object, original, response) => { - assert.equal(object.get("foo"), "bar"); + subscription.on('update', (object, original, response) => { + assert.equal(object.get('foo'), 'bar'); assert.equal(response.installationId, installationId); done(); }); await subscription.subscribePromise; - object.set({ foo: "bar" }); + object.set({ foo: 'bar' }); await object.save(); }); - it("can subscribe to multiple queries", async () => { + it('can subscribe to multiple queries', async () => { const objectA = new TestObject(); const objectB = new TestObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(TestObject); - queryA.equalTo("objectId", objectA.id); - queryB.equalTo("objectId", objectB.id); + queryA.equalTo('objectId', objectA.id); + queryB.equalTo('objectId', objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on("update", (object) => { + subscriptionA.on('update', object => { count++; - assert.equal(object.get("foo"), "bar"); + assert.equal(object.get('foo'), 'bar'); }); - subscriptionB.on("update", (object) => { + subscriptionB.on('update', object => { count++; - assert.equal(object.get("foo"), "baz"); + assert.equal(object.get('foo'), 'baz'); }); - await objectA.save({ foo: "bar" }); - await objectB.save({ foo: "baz" }); + await objectA.save({ foo: 'bar' }); + await objectB.save({ foo: 'baz' }); await sleep(1000); assert.equal(count, 2); }); - it("can subscribe to multiple queries different class", async () => { + it('can subscribe to multiple queries different class', async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo("objectId", objectA.id); - queryB.equalTo("objectId", objectB.id); + queryA.equalTo('objectId', objectA.id); + queryB.equalTo('objectId', objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on("update", (object) => { + subscriptionA.on('update', object => { count++; - assert.equal(object.get("foo"), "bar"); + assert.equal(object.get('foo'), 'bar'); }); - subscriptionB.on("update", (object) => { + subscriptionB.on('update', object => { count++; - assert.equal(object.get("foo"), "baz"); + assert.equal(object.get('foo'), 'baz'); }); - await objectA.save({ foo: "bar" }); - await objectB.save({ foo: "baz" }); + await objectA.save({ foo: 'bar' }); + await objectB.save({ foo: 'baz' }); await sleep(1000); assert.equal(count, 2); }); - it("can unsubscribe to multiple queries different class", async () => { + it('can unsubscribe to multiple queries different class', async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo("objectId", objectA.id); - queryB.equalTo("objectId", objectB.id); + queryA.equalTo('objectId', objectA.id); + queryB.equalTo('objectId', objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on("update", () => { + subscriptionA.on('update', () => { count++; }); - subscriptionB.on("update", (object) => { + subscriptionB.on('update', object => { count++; - assert.equal(object.get("foo"), "baz"); + assert.equal(object.get('foo'), 'baz'); }); subscriptionA.unsubscribe(); - await objectA.save({ foo: "bar" }); - await objectB.save({ foo: "baz" }); + await objectA.save({ foo: 'bar' }); + await objectB.save({ foo: 'baz' }); await sleep(1000); assert.equal(count, 1); }); - it("can unsubscribe with await to multiple queries different class", async () => { + it('can unsubscribe with await to multiple queries different class', async () => { const objectA = new TestObject(); const objectB = new DiffObject(); await Parse.Object.saveAll([objectA, objectB]); const queryA = new Parse.Query(TestObject); const queryB = new Parse.Query(DiffObject); - queryA.equalTo("objectId", objectA.id); - queryB.equalTo("objectId", objectB.id); + queryA.equalTo('objectId', objectA.id); + queryB.equalTo('objectId', objectB.id); const subscriptionA = await queryA.subscribe(); const subscriptionB = await queryB.subscribe(); let count = 0; - subscriptionA.on("update", () => { + subscriptionA.on('update', () => { count++; }); - subscriptionB.on("update", (object) => { + subscriptionB.on('update', object => { count++; - assert.equal(object.get("foo"), "baz"); + assert.equal(object.get('foo'), 'baz'); }); await subscriptionA.unsubscribe(); - await objectA.save({ foo: "bar" }); - await objectB.save({ foo: "baz" }); + await objectA.save({ foo: 'bar' }); + await objectB.save({ foo: 'baz' }); await sleep(1000); assert.equal(count, 1); }); - it("can subscribe to ACL", async (done) => { - const user = await Parse.User.signUp("ooo", "password"); + it('can subscribe to ACL', async done => { + const user = await Parse.User.signUp('ooo', 'password'); const ACL = new Parse.ACL(user); const object = new TestObject(); @@ -171,73 +171,73 @@ describe("Parse LiveQuery", () => { await object.save(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + query.equalTo('objectId', object.id); const subscription = await query.subscribe(user.getSessionToken()); - subscription.on("update", async (object) => { - assert.equal(object.get("foo"), "bar"); + subscription.on('update', async object => { + assert.equal(object.get('foo'), 'bar'); await Parse.User.logOut(); done(); }); - await object.save({ foo: "bar" }); + await object.save({ foo: 'bar' }); }); - it("can subscribe to null sessionToken", async (done) => { - const user = await Parse.User.signUp("oooooo", "password"); + it('can subscribe to null sessionToken', async done => { + const user = await Parse.User.signUp('oooooo', 'password'); const readOnly = Parse.User.readOnlyAttributes(); Parse.User.readOnlyAttributes = null; - user.set("sessionToken", null); + user.set('sessionToken', null); assert.equal(user.getSessionToken(), null); const object = new TestObject(); await object.save(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + query.equalTo('objectId', object.id); const subscription = await query.subscribe(); - subscription.on("update", async (object) => { - assert.equal(object.get("foo"), "bar"); + subscription.on('update', async object => { + assert.equal(object.get('foo'), 'bar'); Parse.User.readOnlyAttributes = function () { return readOnly; }; await Parse.User.logOut(); done(); }); - await object.save({ foo: "bar" }); + 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(); await object.save(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + 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 }); + await object.save({ name: 'hello', age: 21 }); const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); - query.select(["name"]); + query.equalTo('objectId', object.id); + query.select(['name']); const subscription = await query.subscribe(); - subscription.on("update", (object) => { - assert.equal(object.get("name"), "hello"); - assert.equal(object.get("age"), undefined); - assert.equal(object.get("foo"), undefined); + subscription.on('update', object => { + assert.equal(object.get('name'), 'hello'); + assert.equal(object.get('age'), undefined); + assert.equal(object.get('foo'), undefined); done(); }); - object.set({ foo: "bar" }); + object.set({ foo: 'bar' }); await object.save(); }); }); diff --git a/integration/test/ParseLocalDatastoreTest.js b/integration/test/ParseLocalDatastoreTest.js index 09a390572..aa291c72d 100644 --- a/integration/test/ParseLocalDatastoreTest.js +++ b/integration/test/ParseLocalDatastoreTest.js @@ -1,14 +1,14 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); -const TestObject = Parse.Object.extend("TestObject"); -const Item = Parse.Object.extend("Item"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); +const TestObject = Parse.Object.extend('TestObject'); +const Item = Parse.Object.extend('Item'); -global.localStorage = require("./mockLocalStorage"); -const mockRNStorage = require("./mockRNStorage"); -const LocalDatastoreUtils = require("../../lib/node/LocalDatastoreUtils"); +global.localStorage = require('./mockLocalStorage'); +const mockRNStorage = require('./mockRNStorage'); +const LocalDatastoreUtils = require('../../lib/node/LocalDatastoreUtils'); const DEFAULT_PIN = LocalDatastoreUtils.DEFAULT_PIN; const PIN_PREFIX = LocalDatastoreUtils.PIN_PREFIX; @@ -39,10 +39,10 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName("DO_NOT_CLEAR", {}); + await Parse.LocalDatastore.pinWithName('DO_NOT_CLEAR', {}); let storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); @@ -51,8 +51,8 @@ function runTest(controller) { storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 1); - assert.equal(storage["DO_NOT_CLEAR"], "{}"); - await Parse.LocalDatastore.unPinWithName("DO_NOT_CLEAR"); + assert.equal(storage['DO_NOT_CLEAR'], '{}'); + await Parse.LocalDatastore.unPinWithName('DO_NOT_CLEAR'); }); it(`${controller.name} can getAllContents localDatastore`, async () => { @@ -61,17 +61,17 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); await Parse.Object.saveAll(objects); - await Parse.LocalDatastore.pinWithName("DO_NOT_FETCH", {}); + await Parse.LocalDatastore.pinWithName('DO_NOT_FETCH', {}); const storage = await Parse.LocalDatastore._getRawStorage(); assert.equal(Object.keys(storage).length, 6); const LDS = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(LDS).length, 5); - assert.equal(LDS["DO_NOT_FETCH"], null); + assert.equal(LDS['DO_NOT_FETCH'], null); }); it(`${controller.name} can pin (unsaved)`, async () => { @@ -81,9 +81,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); - assert.deepEqual(localDatastore[LDS_KEY(object)], [ - LDS_FULL_JSON(object), - ]); + assert.deepEqual(localDatastore[LDS_KEY(object)], [LDS_FULL_JSON(object)]); await object.save(); // Check if localDatastore updated localId to objectId localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -94,7 +92,7 @@ function runTest(controller) { it(`${controller.name} can store data to pin (unsaved)`, async () => { const object = new TestObject(); - object.set("foo", "bar"); + object.set('foo', 'bar'); await object.pin(); const query = new Parse.Query(TestObject); @@ -103,19 +101,19 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get("foo"), "bar"); - pinnedObject.set("foo", "baz"); + assert.equal(pinnedObject.get('foo'), 'bar'); + pinnedObject.set('foo', 'baz'); await pinnedObject.pin(); results = await query.find(); assert.equal(results.length, 1); pinnedObject = results[0]; - assert.equal(pinnedObject.get("foo"), "baz"); + assert.equal(pinnedObject.get('foo'), 'baz'); }); it(`${controller.name} can query unsaved pin and save`, async () => { const object = new TestObject(); - object.set("foo", "bar"); + object.set('foo', 'bar'); await object.pin(); const query = new Parse.Query(TestObject); @@ -125,9 +123,9 @@ function runTest(controller) { assert.equal(results.length, 1); let pinnedObject = results[0]; - assert.equal(pinnedObject.get("foo"), "bar"); + assert.equal(pinnedObject.get('foo'), 'bar'); - pinnedObject.set("foo", "baz"); + pinnedObject.set('foo', 'baz'); await pinnedObject.save(); assert(pinnedObject.id); @@ -136,7 +134,7 @@ function runTest(controller) { results = await query.find(); pinnedObject = results[0]; - assert.equal(pinnedObject.get("foo"), "baz"); + assert.equal(pinnedObject.get('foo'), 'baz'); assert(pinnedObject.id); assert.equal(pinnedObject._localId, undefined); }); @@ -144,13 +142,13 @@ function runTest(controller) { it(`${controller.name} can pin unsaved pointer`, async () => { const object = new TestObject(); const pointer = new Item(); - object.set("child", pointer); + object.set('child', pointer); await object.pin(); }); it(`${controller.name} can pin user (unsaved)`, async () => { const user = new Parse.User(); - user.set("field", "test"); + user.set('field', 'test'); await user.pin(); const json = user._toFullJSON(); @@ -162,15 +160,15 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, "test"); + assert.equal(cachedObject.field, 'test'); await Parse.User.logOut(); }); it(`${controller.name} can pin user (saved)`, async () => { const user = new Parse.User(); - user.set("field", "test"); - user.setPassword("asdf"); - user.setUsername("zxcv"); + user.set('field', 'test'); + user.setPassword('asdf'); + user.setUsername('zxcv'); await user.signUp(); await user.pin(); @@ -184,13 +182,13 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(user)]); assert.deepEqual(localDatastore[LDS_KEY(user)], [json]); assert.equal(cachedObject.objectId, user.id); - assert.equal(cachedObject.field, "test"); + assert.equal(cachedObject.field, 'test'); await Parse.User.logOut(); }); it(`${controller.name} can pin (saved)`, async () => { const object = new TestObject(); - object.set("field", "test"); + object.set('field', 'test'); await object.save(); await object.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -199,16 +197,16 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, "test"); + assert.equal(cachedObject.field, 'test'); }); it(`${controller.name} can pin (twice saved)`, async () => { const object = new TestObject(); - object.set("field", "test"); + object.set('field', 'test'); await object.save(); await object.pin(); - object.set("field", "new info"); + object.set('field', 'new info'); await object.save(); const localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -217,12 +215,12 @@ function runTest(controller) { assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(object)]); assert.deepEqual(localDatastore[LDS_KEY(object)], [object._toFullJSON()]); assert.equal(cachedObject.objectId, object.id); - assert.equal(cachedObject.field, "new info"); + assert.equal(cachedObject.field, 'new info'); }); it(`${controller.name} can check if pinned`, async () => { const object = new TestObject(); - object.set("field", "test"); + object.set('field', 'test'); await object.save(); let isPinned = await object.isPinned(); @@ -241,34 +239,29 @@ function runTest(controller) { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set("grandchild", grandchild); - parent.set("field", "test"); - parent.set("child", child); + child.set('grandchild', grandchild); + parent.set('field', 'test'); + parent.set('child', child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(parent)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal( - localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), - true - ); + assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(grandchild)), true); assert.deepEqual(localDatastore[LDS_KEY(parent)], [parent._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(child)], [child._toFullJSON()]); - assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [ - grandchild._toFullJSON(), - ]); + assert.deepEqual(localDatastore[LDS_KEY(grandchild)], [grandchild._toFullJSON()]); }); it(`${controller.name} can pin user (recursive)`, async () => { const parent = new TestObject(); const child = new Parse.User(); - child.setUsername("username"); - child.setPassword("password"); + child.setUsername('username'); + child.setPassword('password'); await child.signUp(); - parent.set("field", "test"); - parent.set("child", child); + parent.set('field', 'test'); + parent.set('child', child); await parent.save(); await parent.pin(); @@ -296,11 +289,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -309,11 +298,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -330,11 +315,7 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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()]); @@ -346,11 +327,11 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -363,7 +344,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -380,10 +361,10 @@ function runTest(controller) { const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + 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"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -398,8 +379,8 @@ function runTest(controller) { const obj2 = new TestObject(); await obj1.pin(); await obj2.pin(); - await obj1.pinWithName("test_pin"); - await obj2.pinWithName("test_pin"); + await obj1.pinWithName('test_pin'); + await obj2.pinWithName('test_pin'); await Parse.Object.saveAll([obj1, obj2]); @@ -407,14 +388,8 @@ function runTest(controller) { assert(Object.keys(localDatastore).length === 4); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), - true - ); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); @@ -423,9 +398,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ - LDS_KEY(obj2), - ]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -435,7 +408,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -443,18 +416,9 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), - true - ); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -464,9 +428,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 3); assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj2)]); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_pin"], [ - LDS_KEY(obj2), - ]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj2)]); }); @@ -480,11 +442,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -493,10 +451,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -504,10 +459,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -522,11 +474,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -537,10 +485,7 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_PIN], [LDS_KEY(obj1), LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); }); @@ -589,11 +534,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -623,11 +564,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -651,11 +588,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -687,11 +620,7 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[DEFAULT_PIN], [ - LDS_KEY(obj1), - LDS_KEY(obj2), - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[DEFAULT_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)]); @@ -712,11 +641,11 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName("test_unpin", objects); + await Parse.Object.pinAllWithName('test_unpin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -725,22 +654,18 @@ function runTest(controller) { assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); - await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); + await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); await Parse.Object.saveAll(objects); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -750,11 +675,11 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName("test_unpin", objects); + await Parse.Object.pinAllWithName('test_unpin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -765,12 +690,10 @@ function runTest(controller) { await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllWithName("test_unpin", [obj1, obj2]); + await Parse.Object.unPinAllWithName('test_unpin', [obj1, obj2]); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 2); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ - LDS_KEY(obj3), - ]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj3)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); }); @@ -780,11 +703,11 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName("test_unpin", objects); + await Parse.Object.pinAllWithName('test_unpin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -793,7 +716,7 @@ function runTest(controller) { assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); - await Parse.Object.unPinAllObjectsWithName("test_unpin"); + await Parse.Object.unPinAllObjectsWithName('test_unpin'); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); @@ -816,11 +739,11 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; - await Parse.Object.pinAllWithName("test_unpin", objects); + await Parse.Object.pinAllWithName('test_unpin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + "test_unpin"], [ + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3), @@ -831,7 +754,7 @@ function runTest(controller) { await Parse.Object.saveAll(objects); - await Parse.Object.unPinAllObjectsWithName("test_unpin"); + await Parse.Object.unPinAllObjectsWithName('test_unpin'); localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 3); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); @@ -845,7 +768,7 @@ function runTest(controller) { const obj3 = new TestObject(); const objects = [obj1, obj2, obj3]; await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); await Parse.Object.saveAll(objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); @@ -853,18 +776,9 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj1)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), - true - ); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -880,11 +794,11 @@ function runTest(controller) { const obj2 = new TestObject(); const obj3 = new TestObject(); const child = new TestObject(); - obj1.set("child", child); + obj1.set('child', child); const objects = [obj1, obj2, obj3]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 6); @@ -892,22 +806,10 @@ function runTest(controller) { assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj2)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(obj3)), true); assert.equal(localDatastore[DEFAULT_PIN].includes(LDS_KEY(child)), true); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj1)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj2)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(obj3)), - true - ); - assert.equal( - localDatastore[PIN_PREFIX + "test_pin"].includes(LDS_KEY(child)), - true - ); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj1)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj2)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(obj3)), true); + assert.equal(localDatastore[PIN_PREFIX + 'test_pin'].includes(LDS_KEY(child)), true); assert(localDatastore[LDS_KEY(obj1)]); assert(localDatastore[LDS_KEY(obj2)]); assert(localDatastore[LDS_KEY(obj3)]); @@ -925,7 +827,7 @@ function runTest(controller) { const object = new TestObject(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); + assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); } }); @@ -935,7 +837,7 @@ function runTest(controller) { await object.pin(); await object.fetchFromLocalDatastore(); } catch (e) { - assert.equal(e.message, "Cannot fetch an unsaved ParseObject"); + assert.equal(e.message, 'Cannot fetch an unsaved ParseObject'); } }); @@ -943,8 +845,8 @@ function runTest(controller) { const obj1 = new TestObject(); const obj2 = new TestObject(); - obj1.set("field", "test"); - obj1.set("foo", "bar"); + obj1.set('field', 'test'); + obj1.set('foo', 'bar'); await obj1.pin(); await obj1.save(); @@ -959,10 +861,10 @@ function runTest(controller) { assert.deepEqual(obj1._toFullJSON(), obj3._toFullJSON()); const obj4 = TestObject.createWithoutData(obj1.id); - obj4.set("field", "will not override"); + obj4.set('field', 'will not override'); await obj4.fetchFromLocalDatastore(); - assert.equal(obj4.get("field"), "will not override"); - assert.equal(obj4.get("foo"), "bar"); + assert.equal(obj4.get('field'), 'will not override'); + assert.equal(obj4.get('foo'), 'bar'); }); it(`${controller.name} can fetchFromLocalDatastore with children`, async () => { @@ -971,14 +873,14 @@ function runTest(controller) { const child = new TestObject(); const grandchild = new TestObject(); - obj1.set("field", "test"); - obj1.set("child", child); + obj1.set('field', 'test'); + obj1.set('child', child); await obj1.save(); await obj1.pin(); - grandchild.set("field", "shouldAlsoHave"); - child.set("field", "shouldHave"); - child.set("grandchild", grandchild); + grandchild.set('field', 'shouldAlsoHave'); + child.set('field', 'shouldHave'); + child.set('grandchild', grandchild); await child.save(); obj2.id = obj1.id; @@ -986,16 +888,16 @@ function runTest(controller) { assert.deepEqual(obj1.toJSON(), obj2.toJSON()); assert.deepEqual(obj1._toFullJSON(), obj2._toFullJSON()); - assert.deepEqual(obj2.toJSON().child.field, "shouldHave"); - assert.deepEqual(obj2.toJSON().child.grandchild.field, "shouldAlsoHave"); + assert.deepEqual(obj2.toJSON().child.field, 'shouldHave'); + assert.deepEqual(obj2.toJSON().child.grandchild.field, 'shouldAlsoHave'); }); 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]); /* @@ -1011,14 +913,14 @@ function runTest(controller) { | C */ - A.set("B", B); - A.set("C", C); - A.set("E", E); - A.set("D", D); - B.set("A", A); - C.set("D", D); - D.set("C", C); - E.set("C", C); + A.set('B', B); + A.set('C', C); + A.set('E', E); + A.set('D', D); + B.set('A', A); + C.set('D', D); + D.set('C', C); + E.set('C', C); await Parse.Object.saveAll([A, B, C, D, E]); await A.pin(); @@ -1028,23 +930,23 @@ function runTest(controller) { await object.fetchFromLocalDatastore(); const root = object.toJSON(); - assert.deepEqual(root.B.A.__type, "Pointer"); - assert.deepEqual(root.C.D.C.__type, "Pointer"); - assert.deepEqual(root.E.C.__type, "Object"); - assert.deepEqual(root.D.__type, "Object"); + assert.deepEqual(root.B.A.__type, 'Pointer'); + assert.deepEqual(root.C.D.C.__type, 'Pointer'); + assert.deepEqual(root.E.C.__type, 'Object'); + assert.deepEqual(root.D.__type, 'Object'); }); - it("fetch updates LocalDatastore", async () => { - const item = new Item({ foo: "bar" }); + it('fetch updates LocalDatastore', async () => { + const item = new Item({ foo: 'bar' }); await item.save(); await item.pin(); const params = { id: item.id }; - await Parse.Cloud.run("TestFetchFromLocalDatastore", params); + await Parse.Cloud.run('TestFetchFromLocalDatastore', params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, "bar"); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'bar'); const itemAgain = new Item(); itemAgain.id = item.id; @@ -1052,61 +954,58 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(itemAgain.get("foo"), "changed"); - assert.equal(fetchedItem.get("foo"), "changed"); - assert.equal(localDatastore[LDS_KEY(item)][0].foo, "changed"); + assert.equal(itemAgain.get('foo'), 'changed'); + assert.equal(fetchedItem.get('foo'), 'changed'); + assert.equal(localDatastore[LDS_KEY(item)][0].foo, 'changed'); }); - it("fetchAll updates LocalDatastore", async () => { - const item1 = new Item({ foo: "bar" }); - const item2 = new Item({ foo: "baz" }); + it('fetchAll updates LocalDatastore', async () => { + const item1 = new Item({ foo: 'bar' }); + const item2 = new Item({ foo: 'baz' }); await Parse.Object.saveAll([item1, item2]); await Parse.Object.pinAll([item1, item2]); let params = { id: item1.id }; - await Parse.Cloud.run("TestFetchFromLocalDatastore", params); + await Parse.Cloud.run('TestFetchFromLocalDatastore', params); params = { id: item2.id }; - await Parse.Cloud.run("TestFetchFromLocalDatastore", params); + await Parse.Cloud.run('TestFetchFromLocalDatastore', params); let localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(localDatastore[LDS_KEY(item1)][0].foo, "bar"); - assert.equal(localDatastore[LDS_KEY(item2)][0].foo, "baz"); + assert.equal(localDatastore[LDS_KEY(item1)][0].foo, 'bar'); + assert.equal(localDatastore[LDS_KEY(item2)][0].foo, 'baz'); const item1Again = new Item(); item1Again.id = item1.id; const item2Again = new Item(); item2Again.id = item2.id; - const fetchedItems = await Parse.Object.fetchAll([ - item1Again, - item2Again, - ]); + const fetchedItems = await Parse.Object.fetchAll([item1Again, item2Again]); localDatastore = await Parse.LocalDatastore._getAllContents(); - assert.equal(item1Again.get("foo"), "changed"); - assert.equal(item2Again.get("foo"), "changed"); - assert.equal(fetchedItems[0].get("foo"), "changed"); - assert.equal(fetchedItems[1].get("foo"), "changed"); - assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, "changed"); - assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, "changed"); + assert.equal(item1Again.get('foo'), 'changed'); + assert.equal(item2Again.get('foo'), 'changed'); + assert.equal(fetchedItems[0].get('foo'), 'changed'); + assert.equal(fetchedItems[1].get('foo'), 'changed'); + assert.equal(localDatastore[LDS_KEY(fetchedItems[0])][0].foo, 'changed'); + assert.equal(localDatastore[LDS_KEY(fetchedItems[1])][0].foo, 'changed'); }); it(`${controller.name} can update Local Datastore from network`, async () => { const parent = new TestObject(); const child = new Item(); const grandchild = new Item(); - child.set("grandchild", grandchild); - parent.set("field", "test"); - parent.set("child", child); + child.set('grandchild', grandchild); + parent.set('field', 'test'); + parent.set('child', child); await Parse.Object.saveAll([parent, child, grandchild]); await parent.pin(); // Updates child with { foo: 'changed' } const params = { id: child.id }; - await Parse.Cloud.run("TestFetchFromLocalDatastore", params); + await Parse.Cloud.run('TestFetchFromLocalDatastore', params); Parse.LocalDatastore.isSyncing = false; @@ -1114,7 +1013,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const childJSON = updatedLDS[LDS_KEY(child)]; - assert.equal(childJSON.foo, "changed"); + assert.equal(childJSON.foo, 'changed'); }); it(`${controller.name} can update Local Datastore from network ignore unsaved`, async () => { @@ -1125,7 +1024,7 @@ function runTest(controller) { // Updates item with { foo: 'changed' } const params = { id: item.id }; - await Parse.Cloud.run("TestFetchFromLocalDatastore", params); + await Parse.Cloud.run('TestFetchFromLocalDatastore', params); Parse.LocalDatastore.isSyncing = false; @@ -1133,19 +1032,19 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const itemJSON = updatedLDS[LDS_KEY(item)]; - assert.equal(itemJSON.foo, "changed"); + assert.equal(itemJSON.foo, 'changed'); }); it(`${controller.name} can update Local Datastore User from network`, async () => { const user = new Parse.User(); - user.setUsername("asdf"); - user.setPassword("zxcv"); + user.setUsername('asdf'); + user.setPassword('zxcv'); await user.signUp(); await user.pin(); // Updates user with { foo: 'changed' } const params = { id: user.id }; - await Parse.Cloud.run("UpdateUser", params); + await Parse.Cloud.run('UpdateUser', params); Parse.LocalDatastore.isSyncing = false; @@ -1153,7 +1052,7 @@ function runTest(controller) { const updatedLDS = await Parse.LocalDatastore._getAllContents(); const userJSON = updatedLDS[LDS_KEY(user)]; - assert.equal(userJSON.foo, "changed"); + assert.equal(userJSON.foo, 'changed'); await Parse.User.logOut(); }); }); @@ -1168,7 +1067,7 @@ function runTest(controller) { const numbers = []; for (let i = 0; i < 10; i++) { - numbers[i] = new Parse.Object({ className: "BoxedNumber", number: i }); + numbers[i] = new Parse.Object({ className: 'BoxedNumber', number: i }); } await Parse.Object.saveAll(numbers); await Parse.Object.pinAll(numbers); @@ -1182,15 +1081,15 @@ function runTest(controller) { const objects = [obj1, obj2, obj3, item]; await Parse.Object.saveAll(objects); - await Parse.Object.pinAllWithName("test_pin", objects); + await Parse.Object.pinAllWithName('test_pin', objects); const query = new Parse.Query(TestObject); - query.greaterThan("field", 1); - query.fromPinWithName("test_pin"); + query.greaterThan('field', 1); + query.fromPinWithName('test_pin'); const results = await query.find(); assert.equal(results.length, 2); - assert(results[0].get("field") > 1); - assert(results[1].get("field") > 1); + assert(results[0].get('field') > 1); + assert(results[1].get('field') > 1); }); it(`${controller.name} can query from local datastore`, async () => { @@ -1218,7 +1117,7 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); await obj4.save(); - await obj4.pinWithName("DO_NOT_QUERY"); + await obj4.pinWithName('DO_NOT_QUERY'); const query = new Parse.Query(TestObject); query.fromPin(); @@ -1228,7 +1127,7 @@ function runTest(controller) { }); it(`${controller.name} can query user from pin`, async () => { - const user = await Parse.User.signUp("asdf", "zxcv", { foo: "bar" }); + const user = await Parse.User.signUp('asdf', 'zxcv', { foo: 'bar' }); await user.pin(); const query = new Parse.Query(Parse.User); @@ -1241,22 +1140,22 @@ function runTest(controller) { }); it(`${controller.name} can do basic queries`, async () => { - const baz = new TestObject({ foo: "baz" }); - const qux = new TestObject({ foo: "qux" }); + const baz = new TestObject({ foo: 'baz' }); + const qux = new TestObject({ foo: 'qux' }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); - query.equalTo("foo", "baz"); + query.equalTo('foo', 'baz'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("foo"), "baz"); + assert.equal(results[0].get('foo'), 'baz'); }); it(`${controller.name} can do a query with a limit`, async () => { - const baz = new TestObject({ foo: "baz" }); - const qux = new TestObject({ foo: "qux" }); + const baz = new TestObject({ foo: 'baz' }); + const qux = new TestObject({ foo: 'qux' }); await Parse.Object.saveAll([baz, qux]); await Parse.Object.pinAll([baz, qux]); const query = new Parse.Query(TestObject); @@ -1265,18 +1164,18 @@ function runTest(controller) { const results = await query.find(); assert.equal(results.length, 1); - assert.equal(["baz", "qux"].includes(results[0].get("foo")), true); + assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); }); it(`${controller.name} can do equalTo queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", 3); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it("can do containedBy queries with numbers", async () => { + 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] }), @@ -1287,42 +1186,42 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo("containedBy", true); - query.containedBy("numbers", [1, 2, 3, 4, 5]); + query.equalTo('containedBy', true); + query.containedBy('numbers', [1, 2, 3, 4, 5]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); - it("can do containedBy queries with pointer", async () => { - const objects = Array.from(Array(10).keys()).map((idx) => { - const obj = new Parse.Object("Object"); - obj.set("key", idx); + it('can do containedBy queries with pointer', async () => { + const objects = Array.from(Array(10).keys()).map(idx => { + const obj = new Parse.Object('Object'); + obj.set('key', idx); return obj; }); - const parent1 = new Parse.Object("Parent"); - const parent2 = new Parse.Object("Parent"); - const parent3 = new Parse.Object("Parent"); + const parent1 = new Parse.Object('Parent'); + const parent2 = new Parse.Object('Parent'); + const parent3 = new Parse.Object('Parent'); await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); // [0, 1, 2] - parent1.set("objects", objects.slice(0, 3)); + parent1.set('objects', objects.slice(0, 3)); const shift = objects.shift(); // [2, 0] - parent2.set("objects", [objects[1], shift]); + parent2.set('objects', [objects[1], shift]); // [1, 2, 3, 4] - parent3.set("objects", objects.slice(1, 4)); + parent3.set('objects', objects.slice(1, 4)); await Parse.Object.saveAll([parent1, parent2, parent3]); await Parse.Object.pinAll([parent1, parent2, parent3]); - const query = new Parse.Query("Parent"); - query.containedBy("objects", objects); + const query = new Parse.Query('Parent'); + query.containedBy('objects', objects); query.fromLocalDatastore(); const results = await query.find(); @@ -1331,129 +1230,125 @@ function runTest(controller) { }); it(`${controller.name} can test equality with undefined`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", undefined); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', undefined); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} can perform lessThan queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.lessThan("number", 7); + const query = new Parse.Query('BoxedNumber'); + query.lessThan('number', 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 7); }); it(`${controller.name} can perform lessThanOrEqualTo queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.lessThanOrEqualTo("number", 7); + const query = new Parse.Query('BoxedNumber'); + query.lessThanOrEqualTo('number', 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 8); }); it(`${controller.name} can perform greaterThan queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThan("number", 7); + const query = new Parse.Query('BoxedNumber'); + query.greaterThan('number', 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); }); it(`${controller.name} can perform greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThanOrEqualTo("number", 7); + const query = new Parse.Query('BoxedNumber'); + query.greaterThanOrEqualTo('number', 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 3); }); it(`${controller.name} can combine lessThanOrEqualTo and greaterThanOrEqualTo queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.lessThanOrEqualTo("number", 7); - query.greaterThanOrEqualTo("number", 7); + const query = new Parse.Query('BoxedNumber'); + query.lessThanOrEqualTo('number', 7); + query.greaterThanOrEqualTo('number', 7); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); it(`${controller.name} can combine lessThan and greaterThan queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.lessThan("number", 9); - query.greaterThan("number", 3); + const query = new Parse.Query('BoxedNumber'); + query.lessThan('number', 9); + query.greaterThan('number', 3); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); }); it(`${controller.name} can perform notEqualTo queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.notEqualTo("number", 5); + const query = new Parse.Query('BoxedNumber'); + query.notEqualTo('number', 5); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 9); }); it(`${controller.name} can perform containedIn queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.containedIn("number", [3, 5, 7, 9, 11]); + const query = new Parse.Query('BoxedNumber'); + query.containedIn('number', [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 4); }); it(`${controller.name} can perform notContainedIn queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.notContainedIn("number", [3, 5, 7, 9, 11]); + const query = new Parse.Query('BoxedNumber'); + query.notContainedIn('number', [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 6); }); it(`${controller.name} can test objectId in containedIn queries`, async () => { - const numbers = await new Parse.Query("BoxedNumber") - .ascending("number") - .find(); - const ids = [numbers[2].id, numbers[3].id, "nonsense"]; - const query = new Parse.Query("BoxedNumber"); - query.containedIn("objectId", ids); - query.ascending("number"); + const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); + const ids = [numbers[2].id, numbers[3].id, 'nonsense']; + const query = new Parse.Query('BoxedNumber'); + query.containedIn('objectId', ids); + query.ascending('number'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); - assert.equal(results[0].get("number"), 2); - assert.equal(results[1].get("number"), 3); + assert.equal(results[0].get('number'), 2); + assert.equal(results[1].get('number'), 3); }); it(`${controller.name} can test objectId in equalTo queries`, async () => { - const numbers = await new Parse.Query("BoxedNumber") - .ascending("number") - .find(); + const numbers = await new Parse.Query('BoxedNumber').ascending('number').find(); const id = numbers[5].id; - const query = new Parse.Query("BoxedNumber"); - query.equalTo("objectId", id); - query.ascending("number"); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('objectId', id); + query.ascending('number'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("number"), 5); + assert.equal(results[0].get('number'), 5); }); it(`${controller.name} can find no elements`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", 15); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 15); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 0); }); it(`${controller.name} handles when find throws errors`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("$foo", "bar"); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('$foo', 'bar'); query.fromLocalDatastore(); try { await query.find(); @@ -1491,16 +1386,16 @@ function runTest(controller) { }); it(`${controller.name} can query for the first result`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.descending("number"); + const query = new Parse.Query('BoxedNumber'); + query.descending('number'); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get("number"), 9); + assert.equal(result.get('number'), 9); }); it(`${controller.name} can query for the first with no results`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", 20); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 20); query.fromLocalDatastore(); const result = await query.first(); assert.equal(result, undefined); @@ -1511,16 +1406,16 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo("x", 44); + query.equalTo('x', 44); query.fromLocalDatastore(); const result = await query.first(); - assert.equal(result.get("x"), 44); + assert.equal(result.get('x'), 44); }); it(`${controller.name} handles when first throws errors`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("$foo", "bar"); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('$foo', 'bar'); try { query.fromLocalDatastore(); await query.first(); @@ -1534,18 +1429,18 @@ function runTest(controller) { const item1 = new TestObject(); const item2 = new TestObject(); const container1 = new Parse.Object({ - className: "CoolContainer", + className: 'CoolContainer', item: item1, }); const container2 = new Parse.Object({ - className: "CoolContainer", + className: 'CoolContainer', item: item2, }); const objects = [item1, item2, container1, container2]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query("CoolContainer"); - query.notEqualTo("item", item1); + const query = new Parse.Query('CoolContainer'); + query.notEqualTo('item', item1); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -1561,14 +1456,14 @@ function runTest(controller) { await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo("canSkip", true); + query.equalTo('canSkip', true); query.skip(1); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo("canSkip", true); + query.equalTo('canSkip', true); query.skip(3); query.fromLocalDatastore(); results = await query.find(); @@ -1582,20 +1477,20 @@ function runTest(controller) { new TestObject({ skipCount: true }), ]); let query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); query.fromLocalDatastore(); let count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); query.skip(1); query.fromLocalDatastore(); count = await query.count(); assert.equal(count, 3); query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); query.skip(2); query.fromLocalDatastore(); count = await query.count(); @@ -1603,163 +1498,163 @@ function runTest(controller) { }); it(`${controller.name} can perform count queries`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThan("number", 1); + const query = new Parse.Query('BoxedNumber'); + query.greaterThan('number', 1); query.fromLocalDatastore(); const count = await query.count(); assert.equal(count, 8); }); it(`${controller.name} can order by ascending numbers`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.ascending("number"); + const query = new Parse.Query('BoxedNumber'); + query.ascending('number'); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get("number"), 0); - assert.equal(results[9].get("number"), 9); + assert.equal(results[0].get('number'), 0); + assert.equal(results[9].get('number'), 9); }); it(`${controller.name} can order by descending numbers`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.descending("number"); + const query = new Parse.Query('BoxedNumber'); + query.descending('number'); query.fromLocalDatastore(); const results = await query.find(); - assert.equal(results[0].get("number"), 9); - assert.equal(results[9].get("number"), 0); + assert.equal(results[0].get('number'), 9); + assert.equal(results[9].get('number'), 0); }); it(`${controller.name} can order by ascending number then descending string`, async () => { const objects = [ - 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" }), + 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' }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo("doubleOrder", true); - query.ascending("number").addDescending("string"); + query.equalTo('doubleOrder', true); + query.ascending('number').addDescending('string'); query.fromLocalDatastore(); const results = await query.find(); 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"); + 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'); }); it(`${controller.name} can order by descending number then ascending string`, async () => { const objects = [ - 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" }), + 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' }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo("otherDoubleOrder", true); - query.descending("number").addAscending("string"); + query.equalTo('otherDoubleOrder', true); + query.descending('number').addAscending('string'); query.fromLocalDatastore(); const results = await query.find(); 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"); + 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'); }); it(`${controller.name} can order by descending number and string`, async () => { const objects = [ - 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" }), + 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' }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(TestObject); - query.equalTo("doubleDescending", true); - query.descending("number,string"); + query.equalTo('doubleDescending', true); + query.descending('number,string'); query.fromLocalDatastore(); let results = await query.find(); 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"); + 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'); query = new Parse.Query(TestObject); - query.equalTo("doubleDescending", true); - query.descending("number, string"); + query.equalTo('doubleDescending', true); + query.descending('number, string'); query.fromLocalDatastore(); results = await query.find(); 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"); + 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'); query = new Parse.Query(TestObject); - query.equalTo("doubleDescending", true); - query.descending(["number", "string"]); + query.equalTo('doubleDescending', true); + query.descending(['number', 'string']); query.fromLocalDatastore(); results = await query.find(); 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"); + 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'); query = new Parse.Query(TestObject); - query.equalTo("doubleDescending", true); - query.descending("number", "string"); + query.equalTo('doubleDescending', true); + query.descending('number', 'string'); query.fromLocalDatastore(); results = await query.find(); 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"); + 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'); }); it(`${controller.name} can not order by password`, async () => { - const query = new Parse.Query("BoxedNumber"); - query.ascending("_password"); + const query = new Parse.Query('BoxedNumber'); + query.ascending('_password'); query.fromLocalDatastore(); try { await query.find(); @@ -1771,27 +1666,27 @@ function runTest(controller) { it(`${controller.name} can order by _created_at`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); const obj4 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate", true); - query.ascending("_created_at"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate', true); + query.ascending('_created_at'); query.fromLocalDatastore(); const results = await query.find(); @@ -1802,27 +1697,27 @@ function runTest(controller) { it(`${controller.name} can order by createdAt`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); const obj4 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate2", true); - query.descending("createdAt"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate2', true); + query.descending('createdAt'); query.fromLocalDatastore(); const results = await query.find(); @@ -1833,27 +1728,27 @@ function runTest(controller) { it(`${controller.name} can order by _updated_at`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); const obj4 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate3", true); - query.ascending("_updated_at"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate3', true); + query.ascending('_updated_at'); query.fromLocalDatastore(); const results = await query.find(); @@ -1864,27 +1759,27 @@ function runTest(controller) { it(`${controller.name} can order by updatedAt`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); const obj4 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate4", true); - query.ascending("updatedAt"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate4', true); + query.ascending('updatedAt'); query.fromLocalDatastore(); const results = await query.find(); @@ -1895,66 +1790,66 @@ function runTest(controller) { it(`${controller.name} can test time equality`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item2", + name: 'item2', }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item1", + name: 'item1', }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item3", + name: 'item3', }).save(); const last = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item4", + name: 'item4', }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, last]); - const query = new Parse.Query("TestObject"); - query.equalTo("timed", true); - query.equalTo("createdAt", last.createdAt); + const query = new Parse.Query('TestObject'); + query.equalTo('timed', true); + query.equalTo('createdAt', last.createdAt); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "item4"); + assert.equal(results[0].get('name'), 'item4'); }); it(`${controller.name} can test time inequality`, async () => { const obj1 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item1", + name: 'item1', }).save(); const obj2 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item2", + name: 'item2', }).save(); const obj3 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item3", + name: 'item3', }).save(); const obj4 = await new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item4", + name: 'item4', }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); - let query = new Parse.Query("TestObject"); - query.equalTo("timed2", true); - query.lessThan("createdAt", obj3.createdAt); - query.ascending("createdAt"); + let query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.lessThan('createdAt', obj3.createdAt); + query.ascending('createdAt'); query.fromLocalDatastore(); let results = await query.find(); @@ -1962,9 +1857,9 @@ function runTest(controller) { assert.equal(results[0].id, obj1.id); assert.equal(results[1].id, obj2.id); - query = new Parse.Query("TestObject"); - query.equalTo("timed2", true); - query.greaterThan("createdAt", obj3.createdAt); + query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.greaterThan('createdAt', obj3.createdAt); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); @@ -1973,43 +1868,43 @@ function runTest(controller) { it(`${controller.name} can test string matching`, async () => { const obj1 = new TestObject(); - obj1.set("myString", "football"); + obj1.set('myString', 'football'); const obj2 = new TestObject(); - obj2.set("myString", "soccer"); + obj2.set('myString', 'soccer'); await Parse.Object.saveAll([obj1, obj2]); await Parse.Object.pinAll([obj1, obj2]); let query = new Parse.Query(TestObject); - query.matches("myString", "^fo*\\wb[^o]l+$"); + query.matches('myString', '^fo*\\wb[^o]l+$'); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "football"); + assert.equal(results[0].get('myString'), 'football'); query = new Parse.Query(TestObject); - query.matches("myString", /^fo*\wb[^o]l+$/); + query.matches('myString', /^fo*\wb[^o]l+$/); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "football"); + assert.equal(results[0].get('myString'), 'football'); }); it(`${controller.name} can test case insensitive regex`, async () => { const obj = new TestObject(); - obj.set("myString", "hockey"); + obj.set('myString', 'hockey'); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.matches("myString", "Hockey", "i"); + query.matches('myString', 'Hockey', 'i'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "hockey"); + assert.equal(results[0].get('myString'), 'hockey'); }); it(`${controller.name} fails for invalid regex options`, async () => { const query = new Parse.Query(TestObject); - query.matches("myString", "football", "some invalid thing"); + query.matches('myString', 'football', 'some invalid thing'); query.fromLocalDatastore(); try { await query.find(); @@ -2021,12 +1916,12 @@ function runTest(controller) { it(`${controller.name} can use a regex with all modifiers`, async () => { const obj = new TestObject(); - obj.set("website", "\n\nbuffer\n\nparse.COM"); + obj.set('website', '\n\nbuffer\n\nparse.COM'); await obj.save(); 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); @@ -2034,12 +1929,12 @@ function runTest(controller) { it(`${controller.name} can include regexp modifiers in the constructor`, async () => { const obj = new TestObject(); - obj.set("website", "\n\nbuffer\n\nparse.COM"); + obj.set('website', '\n\nbuffer\n\nparse.COM'); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.matches("website", /parse\.com/im); + query.matches('website', /parse\.com/im); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -2050,24 +1945,24 @@ function runTest(controller) { "\\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: '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); let query = new Parse.Query(TestObject); - query.equalTo("contains", true); - query.startsWith("myString", someAscii); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); query.fromLocalDatastore(); let results = await query.find(); assert.equal(results.length, 2); query = new Parse.Query(TestObject); - query.equalTo("contains", true); - query.startsWith("myString", someAscii); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); query.fromLocalDatastore(); results = await query.find(); assert.equal(results.length, 2); @@ -2078,9 +1973,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject(); if (i % 2) { - item.set("y", i + 1); + item.set('y', i + 1); } else { - item.set("z", i + 1); + item.set('z', i + 1); } objects.push(item); } @@ -2088,12 +1983,12 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.exists("y"); + query.exists('y'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("y")); + assert(results[i].has('y')); } }); @@ -2102,9 +1997,9 @@ function runTest(controller) { for (let i = 0; i < 10; i++) { const item = new TestObject({ dne: true }); if (i % 2) { - item.set("y", i + 1); + item.set('y', i + 1); } else { - item.set("z", i + 1); + item.set('z', i + 1); } objects.push(item); } @@ -2112,28 +2007,28 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); - query.equalTo("dne", true); - query.doesNotExist("y"); + query.equalTo('dne', true); + query.doesNotExist('y'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("z")); + assert(results[i].has('z')); } }); 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", { + const container = new Parse.Object('Container', { relation_exists: true, }); if (i % 2) { - container.set("y", i); + container.set('y', i); } else { const item = new TestObject(); - item.set("x", i); - container.set("x", item); + item.set('x', i); + container.set('x', item); objects.push(item); } objects.push(container); @@ -2141,27 +2036,27 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query("Container"); - query.equalTo("relation_exists", true); - query.exists("x"); + const query = new Parse.Query('Container'); + query.equalTo('relation_exists', true); + query.exists('x'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("x")); + assert(results[i].has('x')); } }); it(`${controller.name} can test if a relation does not exist`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const container = new Parse.Object("Container", { relation_dne: true }); + const container = new Parse.Object('Container', { relation_dne: true }); if (i % 2) { - container.set("y", i); + container.set('y', i); } else { const item = new TestObject(); - item.set("x", i); - container.set("x", item); + item.set('x', i); + container.set('x', item); objects.push(item); } objects.push(container); @@ -2169,14 +2064,14 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const query = new Parse.Query("Container"); - query.equalTo("relation_dne", true); - query.doesNotExist("x"); + const query = new Parse.Query('Container'); + query.equalTo('relation_dne', true); + query.doesNotExist('x'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("y")); + assert(results[i].has('y')); } }); @@ -2202,96 +2097,96 @@ function runTest(controller) { it(`${controller.name} can include nested objects`, async () => { const child = new TestObject(); - const parent = new Parse.Object("Container"); - child.set("foo", "bar"); - parent.set("child", child); + const parent = new Parse.Object('Container'); + child.set('foo', 'bar'); + parent.set('child', child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); - query.include("child"); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include('child'); query.fromLocalDatastore(); const results = await query.find(); 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"); + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert.equal(parentAgain.get('child').get('foo'), 'bar'); }); it(`${controller.name} can includeAll nested objects`, async () => { - const child1 = new TestObject({ foo: "bar" }); - const child2 = new TestObject({ foo: "baz" }); - const child3 = new TestObject({ foo: "bin" }); - const parent = new Parse.Object("Container"); - parent.set("child1", child1); - parent.set("child2", child2); - parent.set("child3", child3); + const child1 = new TestObject({ foo: 'bar' }); + const child2 = new TestObject({ foo: 'baz' }); + const child3 = new TestObject({ foo: 'bin' }); + const parent = new Parse.Object('Container'); + parent.set('child1', child1); + parent.set('child2', child2); + parent.set('child3', child3); await Parse.Object.saveAll([child1, child2, child3, parent]); await Parse.Object.pinAll([child1, child2, child3, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); query.includeAll(); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - assert.equal(parentAgain.get("child1").get("foo"), "bar"); - assert.equal(parentAgain.get("child2").get("foo"), "baz"); - assert.equal(parentAgain.get("child3").get("foo"), "bin"); + assert.equal(parentAgain.get('child1').get('foo'), 'bar'); + assert.equal(parentAgain.get('child2').get('foo'), 'baz'); + assert.equal(parentAgain.get('child3').get('foo'), 'bin'); }); it(`${controller.name} can includeAll nested objects in .each`, async () => { - const child1 = new TestObject({ foo: "bar" }); - const child2 = new TestObject({ foo: "baz" }); - const child3 = new TestObject({ foo: "bin" }); - const parent = new Parse.Object("Container"); - parent.set("child1", child1); - parent.set("child2", child2); - parent.set("child3", child3); + const child1 = new TestObject({ foo: 'bar' }); + const child2 = new TestObject({ foo: 'baz' }); + const child3 = new TestObject({ foo: 'bin' }); + const parent = new Parse.Object('Container'); + parent.set('child1', child1); + parent.set('child2', child2); + parent.set('child3', child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); query.includeAll(); query.fromLocalDatastore(); - 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"); + 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'); }); }); it(`${controller.name} can include nested objects via array`, async () => { const child = new TestObject(); - const parent = new Parse.Object("Container"); - child.set("foo", "bar"); - parent.set("child", child); + const parent = new Parse.Object('Container'); + child.set('foo', 'bar'); + parent.set('child', child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); - query.include(["child"]); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include(['child']); query.fromLocalDatastore(); const results = await query.find(); 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"); + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert.equal(parentAgain.get('child').get('foo'), 'bar'); }); it(`${controller.name} can do a nested include`, async () => { - const Child = Parse.Object.extend("Child"); - const Parent = Parse.Object.extend("Parent"); - const Grandparent = Parse.Object.extend("Grandparent"); + const Child = Parse.Object.extend('Child'); + const Parent = Parse.Object.extend('Parent'); + const Grandparent = Parse.Object.extend('Grandparent'); const objects = []; for (let i = 0; i < 5; i++) { @@ -2312,79 +2207,79 @@ function runTest(controller) { await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q = new Parse.Query("Grandparent"); - q.equalTo("nested", true); - q.include("parent.child"); + const q = new Parse.Query('Grandparent'); + q.equalTo('nested', true); + q.include('parent.child'); q.fromLocalDatastore(); const results = await q.find(); 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")); + 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')); }); }); it(`${controller.name} can include without changing dirty`, async () => { - const parent = new Parse.Object("ParentObject"); - const child = new Parse.Object("ChildObject"); - parent.set("child", child); - child.set("foo", "bar"); + const parent = new Parse.Object('ParentObject'); + const child = new Parse.Object('ChildObject'); + parent.set('child', child); + child.set('foo', 'bar'); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - const query = new Parse.Query("ParentObject"); - query.include("child"); - query.equalTo("objectId", parent.id); + const query = new Parse.Query('ParentObject'); + query.include('child'); + query.equalTo('objectId', parent.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get("child"); + const childAgain = parentAgain.get('child'); assert.equal(child.id, childAgain.id); assert.equal(parent.id, parentAgain.id); - assert.equal(childAgain.get("foo"), "bar"); + assert.equal(childAgain.get('foo'), 'bar'); assert(!parentAgain.dirty()); assert(!childAgain.dirty()); }); it(`${controller.name} uses subclasses when creating objects`, async () => { - const ParentObject = Parse.Object.extend({ className: "ParentObject" }); - let ChildObject = Parse.Object.extend("ChildObject", { + const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); + let ChildObject = Parse.Object.extend('ChildObject', { foo() { - return "foo"; + return 'foo'; }, }); const parent = new ParentObject(); const child = new ChildObject(); - parent.set("child", child); + parent.set('child', child); await Parse.Object.saveAll([child, parent]); await Parse.Object.pinAll([child, parent]); - ChildObject = Parse.Object.extend("ChildObject", { + ChildObject = Parse.Object.extend('ChildObject', { bar() { - return "bar"; + return 'bar'; }, }); const query = new Parse.Query(ParentObject); - query.equalTo("objectId", parent.id); - query.include("child"); + query.equalTo('objectId', parent.id); + query.include('child'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get("child"); - assert.equal(childAgain.foo(), "foo"); - assert.equal(childAgain.bar(), "bar"); + const childAgain = parentAgain.get('child'); + assert.equal(childAgain.foo(), 'foo'); + assert.equal(childAgain.bar(), 'bar'); }); it(`${controller.name} can match the results of another query`, async () => { - const ParentObject = Parse.Object.extend("ParentObject"); - const ChildObject = Parse.Object.extend("ChildObject"); + const ParentObject = Parse.Object.extend('ParentObject'); + const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { objects.push( @@ -2398,22 +2293,22 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo("qtest", true); - subQuery.greaterThan("x", 5); + subQuery.equalTo('qtest', true); + subQuery.greaterThan('x', 5); const q = new Parse.Query(ParentObject); - q.matchesQuery("child", subQuery); + q.matchesQuery('child', subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 4); - results.forEach((o) => { - assert(o.get("x") > 15); + results.forEach(o => { + assert(o.get('x') > 15); }); }); it(`${controller.name} can not match the results of another query`, async () => { - const ParentObject = Parse.Object.extend("ParentObject"); - const ChildObject = Parse.Object.extend("ChildObject"); + const ParentObject = Parse.Object.extend('ParentObject'); + const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { objects.push( @@ -2428,87 +2323,87 @@ function runTest(controller) { await Parse.Object.pinAll(objects); const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo("dneqtest", true); - subQuery.greaterThan("x", 5); + subQuery.equalTo('dneqtest', true); + subQuery.greaterThan('x', 5); const q = new Parse.Query(ParentObject); - q.equalTo("dneqtest", true); - q.doesNotMatchQuery("child", subQuery); + q.equalTo('dneqtest', true); + q.doesNotMatchQuery('child', subQuery); q.fromLocalDatastore(); const results = await q.find(); assert.equal(results.length, 6); - results.forEach((o) => { - assert(o.get("x") >= 10); - assert(o.get("x") <= 15); + results.forEach(o => { + assert(o.get('x') >= 10); + assert(o.get('x') <= 15); }); }); it(`${controller.name} can select keys from a matched query`, async () => { - const Restaurant = Parse.Object.extend("Restaurant"); - const Person = Parse.Object.extend("Person"); + const Restaurant = Parse.Object.extend('Restaurant'); + const Person = Parse.Object.extend('Person'); const objects = [ - new Restaurant({ rating: 5, location: "Djibouti" }), - new Restaurant({ rating: 3, location: "Ouagadougou" }), - new Person({ name: "Bob", hometown: "Djibouti" }), - new Person({ name: "Tom", hometown: "Ouagadougou" }), - new Person({ name: "Billy", hometown: "Detroit" }), + new Restaurant({ rating: 5, location: 'Djibouti' }), + new Restaurant({ rating: 3, location: 'Ouagadougou' }), + new Person({ name: 'Bob', hometown: 'Djibouti' }), + new Person({ name: 'Tom', hometown: 'Ouagadougou' }), + new Person({ name: 'Billy', hometown: 'Detroit' }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); let query = new Parse.Query(Restaurant); - query.greaterThan("rating", 4); + query.greaterThan('rating', 4); let mainQuery = new Parse.Query(Person); - mainQuery.matchesKeyInQuery("hometown", "location", query); + mainQuery.matchesKeyInQuery('hometown', 'location', query); mainQuery.fromLocalDatastore(); let results = await mainQuery.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "Bob"); + assert.equal(results[0].get('name'), 'Bob'); query = new Parse.Query(Restaurant); - query.greaterThan("rating", 4); + query.greaterThan('rating', 4); mainQuery = new Parse.Query(Person); - mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); - mainQuery.ascending("name"); + mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); + mainQuery.ascending('name'); mainQuery.fromLocalDatastore(); results = await mainQuery.find(); assert.equal(results.length, 2); - assert(["Billy", "Tom"].includes(results[0].get("name"))); - assert(["Billy", "Tom"].includes(results[1].get("name"))); + assert(['Billy', 'Tom'].includes(results[0].get('name'))); + assert(['Billy', 'Tom'].includes(results[1].get('name'))); }); it(`${controller.name} supports objects with length`, async () => { const obj = new TestObject(); - obj.set("length", 5); - assert.equal(obj.get("length"), 5); + obj.set('length', 5); + assert.equal(obj.get('length'), 5); await obj.save(); await obj.pin(); const query = new Parse.Query(TestObject); - query.equalTo("objectId", obj.id); + query.equalTo('objectId', obj.id); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); - assert.equal(results[0].get("length"), 5); + assert.equal(results[0].get('length'), 5); }); it(`${controller.name} can include User fields`, async () => { - const user = await Parse.User.signUp("bob", "password", { age: 21 }); + const user = await Parse.User.signUp('bob', 'password', { age: 21 }); const obj = new TestObject(); await obj.save({ owner: user }); await obj.pin(); const query = new Parse.Query(TestObject); - query.include("owner"); + query.include('owner'); query.fromLocalDatastore(); const objAgain = await query.get(obj.id); - assert(objAgain.get("owner") instanceof Parse.User); - assert.equal(objAgain.get("owner").get("age"), 21); + assert(objAgain.get('owner') instanceof Parse.User); + assert.equal(objAgain.get('owner').get('age'), 21); try { await Parse.User.logOut(); } catch (e) { @@ -2519,55 +2414,55 @@ function runTest(controller) { it(`${controller.name} can build OR queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object("BoxedNumber"); + const obj = new Parse.Object('BoxedNumber'); obj.set({ x: i, orquery: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query("BoxedNumber"); - q1.equalTo("orquery", true); - q1.lessThan("x", 2); + 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 q2 = new Parse.Query('BoxedNumber'); + q2.equalTo('orquery', true); + q2.greaterThan('x', 5); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); const results = await orQuery.find(); assert.equal(results.length, 6); - results.forEach((number) => { - assert(number.get("x") < 2 || number.get("x") > 5); + results.forEach(number => { + assert(number.get('x') < 2 || number.get('x') > 5); }); }); it(`${controller.name} can build complex OR queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object("Child"); - child.set("x", i); - child.set("complexor", true); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("complexor", true); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + child.set('complexor', true); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('complexor', true); + parent.set('y', i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query("Child"); - subQuery.equalTo("x", 4); - subQuery.equalTo("complexor", true); + 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 q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query("Parent"); - q2.equalTo("complexor", true); - q2.lessThan("y", 2); + const q2 = new Parse.Query('Parent'); + q2.equalTo('complexor', true); + q2.lessThan('y', 2); const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); @@ -2578,55 +2473,55 @@ function runTest(controller) { it(`${controller.name} can build AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object("BoxedNumber"); + const obj = new Parse.Object('BoxedNumber'); obj.set({ x: i, and: true }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query("BoxedNumber"); - q1.equalTo("and", true); - q1.greaterThan("x", 2); + 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 q2 = new Parse.Query('BoxedNumber'); + q2.equalTo('and', true); + q2.lessThan('x', 5); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); const results = await andQuery.find(); assert.equal(results.length, 2); - results.forEach((number) => { - assert(number.get("x") > 2 && number.get("x") < 5); + results.forEach(number => { + assert(number.get('x') > 2 && number.get('x') < 5); }); }); it(`${controller.name} can build complex AND queries`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object("Child"); - child.set("x", i); - child.set("and", true); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("and", true); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + child.set('and', true); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('and', true); + parent.set('y', i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query("Child"); - subQuery.equalTo("x", 4); - subQuery.equalTo("and", true); + 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 q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query("Parent"); - q2.equalTo("and", true); - q2.equalTo("y", 4); + const q2 = new Parse.Query('Parent'); + q2.equalTo('and', true); + q2.equalTo('y', 4); const andQuery = Parse.Query.and(q1, q2); andQuery.fromLocalDatastore(); @@ -2637,53 +2532,53 @@ function runTest(controller) { it(`${controller.name} can build NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const obj = new Parse.Object("NORTest"); + const obj = new Parse.Object('NORTest'); obj.set({ x: i }); objects.push(obj); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const q1 = new Parse.Query("NORTest"); - q1.greaterThan("x", 5); - const q2 = new Parse.Query("NORTest"); - q2.lessThan("x", 3); + const q1 = new Parse.Query('NORTest'); + q1.greaterThan('x', 5); + const q2 = new Parse.Query('NORTest'); + q2.lessThan('x', 3); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 3); - results.forEach((number) => { - assert(number.get("x") >= 3 && number.get("x") <= 5); + results.forEach(number => { + assert(number.get('x') >= 3 && number.get('x') <= 5); }); }); it(`${controller.name} can build complex NOR queries`, async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const child = new Parse.Object("Child"); - child.set("x", i); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('y', i); objects.push(parent); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); - const subQuery = new Parse.Query("Child"); - subQuery.equalTo("x", 4); - const q1 = new Parse.Query("Parent"); - q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query("Parent"); - q2.equalTo("y", 5); + const subQuery = new Parse.Query('Child'); + subQuery.equalTo('x', 4); + const q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); + const q2 = new Parse.Query('Parent'); + q2.equalTo('y', 5); const norQuery = Parse.Query.nor(q1, q2); norQuery.fromLocalDatastore(); const results = await norQuery.find(); assert.equal(results.length, 8); - results.forEach((number) => { - assert(number.get("x") !== 4 || number.get("x") !== 5); + results.forEach(number => { + assert(number.get('x') !== 4 || number.get('x') !== 5); }); }); @@ -2697,11 +2592,11 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + query.equalTo('eachtest', true); + query.lessThan('x', 25); query.fromLocalDatastore(); - await query.each((obj) => { - seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; + await query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); assert.equal(seen.length, 25); for (let i = 0; i < seen.length; i++) { @@ -2719,16 +2614,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); - query.ascending("x"); + query.equalTo('eachtest', true); + query.lessThan('x', 25); + query.ascending('x'); query.fromLocalDatastore(); try { - await query.each((obj) => { - seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; + await query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { - assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); + assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); } }); @@ -2742,16 +2637,16 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + query.equalTo('eachtest', true); + query.lessThan('x', 25); query.limit(20); query.fromLocalDatastore(); try { - await query.each((obj) => { - seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; + await query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { - assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); + assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); } }); @@ -2765,27 +2660,27 @@ function runTest(controller) { await Parse.Object.pinAll(items); const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + query.equalTo('eachtest', true); + query.lessThan('x', 25); query.skip(20); query.fromLocalDatastore(); try { - await query.each((obj) => { - seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; + await query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { - assert.equal(e, "Cannot iterate on a query with sort, skip, or limit."); + assert.equal(e, 'Cannot iterate on a query with sort, skip, or limit.'); } }); it(`${controller.name} can select specific keys`, async () => { - const obj = new TestObject({ foo: "baz", bar: 1 }); + const obj = new TestObject({ foo: 'baz', bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo("objectId", obj.id); - q.select("foo"); + q.equalTo('objectId', obj.id); + q.select('foo'); q.fromLocalDatastore(); const result = await q.first(); @@ -2793,23 +2688,23 @@ function runTest(controller) { assert(result.createdAt); assert(result.updatedAt); assert(!result.dirty()); - assert.equal(result.get("foo"), "baz"); - assert.equal(result.get("bar"), undefined); + assert.equal(result.get('foo'), 'baz'); + assert.equal(result.get('bar'), undefined); }); it(`${controller.name} can select specific keys with each`, async () => { - const obj = new TestObject({ foo: "baz", bar: 1 }); + const obj = new TestObject({ foo: 'baz', bar: 1 }); await obj.save(); await obj.pin(); const q = new Parse.Query(TestObject); - q.equalTo("objectId", obj.id); - q.select("foo"); + 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); + assert.equal(o.get('foo'), 'baz'); + assert.equal(o.get('bar'), undefined); }); }); @@ -2820,33 +2715,33 @@ function runTest(controller) { await obj.pin(); let q = new Parse.Query(TestObject); - q.equalTo("dateField", now); + q.equalTo('dateField', now); q.fromLocalDatastore(); let objects = await q.find(); assert.equal(objects.length, 1); const future = new Date(now.getTime() + 1000); q = new Parse.Query(TestObject); - q.lessThan("dateField", future); + q.lessThan('dateField', future); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.lessThanOrEqualTo("dateField", now); + q.lessThanOrEqualTo('dateField', now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); const past = new Date(now.getTime() - 1000); q = new Parse.Query(TestObject); - q.greaterThan("dateField", past); + q.greaterThan('dateField', past); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); q = new Parse.Query(TestObject); - q.greaterThanOrEqualTo("dateField", now); + q.greaterThanOrEqualTo('dateField', now); q.fromLocalDatastore(); objects = await q.find(); assert.equal(objects.length, 1); @@ -2854,16 +2749,16 @@ function runTest(controller) { it(`${controller.name} supports withinPolygon`, async () => { const sacramento = new TestObject(); - sacramento.set("location", new Parse.GeoPoint(38.52, -121.5)); - sacramento.set("name", "Sacramento"); + sacramento.set('location', new Parse.GeoPoint(38.52, -121.5)); + sacramento.set('name', 'Sacramento'); const honolulu = new TestObject(); - honolulu.set("location", new Parse.GeoPoint(21.35, -157.93)); - honolulu.set("name", "Honolulu"); + honolulu.set('location', new Parse.GeoPoint(21.35, -157.93)); + honolulu.set('name', 'Honolulu'); const sf = new TestObject(); - sf.set("location", new Parse.GeoPoint(37.75, -122.68)); - sf.set("name", "San Francisco"); + sf.set('location', new Parse.GeoPoint(37.75, -122.68)); + sf.set('name', 'San Francisco'); await Parse.Object.saveAll([sacramento, honolulu, sf]); await Parse.Object.pinAll([sacramento, honolulu, sf]); @@ -2875,7 +2770,7 @@ function runTest(controller) { new Parse.GeoPoint(37.68, -122.33), ]; const query = new Parse.Query(TestObject); - query.withinPolygon("location", points); + query.withinPolygon('location', points); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -2915,7 +2810,7 @@ function runTest(controller) { const point = new Parse.GeoPoint(0.5, 0.5); const query = new Parse.Query(TestObject); - query.polygonContains("polygon", point); + query.polygonContains('polygon', point); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 2); @@ -2924,76 +2819,70 @@ function runTest(controller) { it(`${controller.name} can query from pin subclass`, async () => { class ClassA extends Parse.Object { constructor() { - super("ClassA"); + super('ClassA'); } get name() { - return this.get("name"); + return this.get('name'); } set name(value) { - this.set("name", value); + this.set('name', value); } } - Parse.Object.registerSubclass("ClassA", ClassA); + Parse.Object.registerSubclass('ClassA', ClassA); class ClassB extends Parse.Object { constructor() { - super("ClassB"); + super('ClassB'); } get name() { - return this.get("name"); + return this.get('name'); } set name(value) { - this.set("name", value); + this.set('name', value); } get classA() { - return this.get("classA"); + return this.get('classA'); } set classA(value) { - this.set("classA", value); + this.set('classA', value); } } - Parse.Object.registerSubclass("ClassB", ClassB); + Parse.Object.registerSubclass('ClassB', ClassB); const testClassA = new ClassA(); - testClassA.name = "ABC"; + testClassA.name = 'ABC'; await testClassA.pin(); const query = new Parse.Query(ClassA); query.fromLocalDatastore(); - query.equalTo("name", "ABC"); + query.equalTo('name', 'ABC'); const result = await query.first(); - expect(result.get("name")).toBe("ABC"); + expect(result.get('name')).toBe('ABC'); const testClassB = new ClassB(); - testClassB.name = "XYZ"; + testClassB.name = 'XYZ'; testClassB.classA = testClassA; await testClassB.pin(); let localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual( - testClassA.toOfflinePointer() - ); + expect(localDatastore[LDS_KEY(testClassB)][0].classA).toEqual(testClassA.toOfflinePointer()); await testClassB.save(); expect(testClassB.classA).toBe(testClassA); expect(testClassA.id).toBeDefined(); localDatastore = await Parse.LocalDatastore._getAllContents(); - expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual( - testClassA.id - ); + expect(localDatastore[LDS_KEY(testClassB)][0].classA.objectId).toEqual(testClassA.id); }); }); } -describe("Parse LocalDatastore", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); - Parse.CoreManager.getInstallationController()._setInstallationIdCache( - "1234" - ); +describe('Parse LocalDatastore', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.CoreManager.getInstallationController()._setInstallationIdCache('1234'); Parse.enableLocalDatastore(); Parse.User.enableUnsafeCurrentUser(); Parse.Storage._clear(); @@ -3003,10 +2892,10 @@ describe("Parse LocalDatastore", () => { }); const controllers = [ - { name: "Default", file: "../../lib/node/LocalDatastoreController" }, + { name: 'Default', file: '../../lib/node/LocalDatastoreController' }, { - name: "React-Native", - file: "../../lib/node/LocalDatastoreController.react-native", + name: 'React-Native', + file: '../../lib/node/LocalDatastoreController.react-native', }, ]; diff --git a/integration/test/ParseMasterKeyTest.js b/integration/test/ParseMasterKeyTest.js index 5b150a9e9..2867d541a 100644 --- a/integration/test/ParseMasterKeyTest.js +++ b/integration/test/ParseMasterKeyTest.js @@ -1,34 +1,34 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Master Key", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Master Key', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it("can perform a simple save", (done) => { + it('can perform a simple save', done => { const object = new TestObject(); - object.set("color", "purple"); + object.set('color', 'purple'); object.save(null, { useMasterKey: true }).then(() => { assert(object.id); done(); }); }); - 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) => { + Parse.User.signUp('andrew', 'password') + .then(user => { object = new TestObject({ ACL: new Parse.ACL(user) }); return object.save(); }) @@ -40,11 +40,11 @@ describe("Master Key", () => { // expect success done(); }) - .catch((e) => console.log(e)); + .catch(e => console.log(e)); }); - it("throws when no master key is provided", (done) => { - Parse.CoreManager.set("MASTER_KEY", null); + 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(() => { // should fail diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index bd406bd7e..777b1d5cb 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -1,83 +1,83 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); -const Item = Parse.Object.extend("Item"); -const Container = Parse.Object.extend("Container"); +const TestObject = Parse.Object.extend('TestObject'); +const Item = Parse.Object.extend('Item'); +const Container = Parse.Object.extend('Container'); -describe("Parse Object", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Object', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it("can create objects", (done) => { - const object = new TestObject({ test: "test" }); - object.save().then((o) => { + it('can create objects', done => { + const object = new TestObject({ test: 'test' }); + object.save().then(o => { assert(o); assert(o.id); - assert.equal(o.get("test"), "test"); + assert.equal(o.get('test'), 'test'); done(); }); }); - it("can update objects", (done) => { - const object = new TestObject({ test: "test" }); + it('can update objects', done => { + const object = new TestObject({ test: 'test' }); object .save() - .then((o) => { + .then(o => { const o2 = new TestObject({ objectId: o.id }); - o2.set("test", "changed"); + o2.set('test', 'changed'); return o2.save(); }) - .then((o) => { - assert.equal(o.get("test"), "changed"); + .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.set('b', b); a.save() .then(() => { - b.set("a", a); + 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); + assert.equal(a.get('b').id, b.id); + assert.equal(b.get('a').id, a.id); done(); }); }); - it("can get objects", (done) => { - const object = new TestObject({ test: "test" }); + 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"); + .then(o => { + assert.equal(o.get('test'), 'test'); assert.equal(o.id, object.id); done(); }); }); - it("can delete an object", (done) => { - const object = new TestObject({ test: "test" }); + it('can delete an object', done => { + const object = new TestObject({ test: 'test' }); object .save() .then(() => { @@ -86,13 +86,13 @@ describe("Parse Object", () => { .then(() => { return object.fetch(); }) - .catch((e) => { + .catch(e => { assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); done(); }); }); - it("can check if object exists", async () => { + it('can check if object exists', async () => { const object = new TestObject(); assert.equal(await object.exists(), false); await object.save(); @@ -101,45 +101,45 @@ describe("Parse Object", () => { assert.equal(await object.exists(), false); }); - it("can find objects", (done) => { - const object = new TestObject({ foo: "bar" }); + it('can find objects', done => { + const object = new TestObject({ foo: 'bar' }); object .save() .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("foo", "bar"); + query.equalTo('foo', 'bar'); return query.find(); }) - .then((results) => { + .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"); + item.set('property', 'x'); const container = new Container(); - container.set("item", item); + container.set('item', item); Parse.Object.saveAll([item, container]) .then(() => { const query = new Parse.Query(Container); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); const containerAgain = results[0]; - const itemAgain = containerAgain.get("item"); + const itemAgain = containerAgain.get('item'); return itemAgain.fetch(); }) - .then((itemAgain) => { - assert.equal(itemAgain.get("property"), "x"); + .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; @@ -151,11 +151,11 @@ 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"); + item.set('property', 'x'); const container = new Container(); - container.set("item", item); + container.set('item', item); container .save() @@ -163,20 +163,20 @@ describe("Parse Object", () => { const query = new Parse.Query(Container); return query.get(container.id); }) - .then((result) => { + .then(result => { assert(result); const containerAgain = result; - const itemAgain = containerAgain.get("item"); + const itemAgain = containerAgain.get('item'); return itemAgain.fetch(); }) - .then((itemAgain) => { - assert.equal(itemAgain.get("property"), "x"); + .then(itemAgain => { + assert.equal(itemAgain.get('property'), 'x'); done(); }); }); - it("can fetch server data", (done) => { - const item = new Item({ foo: "bar" }); + it('can fetch server data', done => { + const item = new Item({ foo: 'bar' }); item .save() .then(() => { @@ -184,60 +184,60 @@ describe("Parse Object", () => { itemAgain.id = item.id; return itemAgain.fetch(); }) - .then((itemAgain) => { - assert.equal(itemAgain.get("foo"), "bar"); - return itemAgain.save({ foo: "baz" }); + .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")); + .then(itemAgain => { + assert.equal(item.get('foo'), itemAgain.get('foo')); done(); }) .catch(done.fail); }); - it("does not remove old fields on fetch", (done) => { - const object = new Parse.Object("SimpleObject"); - object.set("foo", "bar"); - object.set("test", "foo"); + 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"); + const query = new Parse.Query('SimpleObject'); return query.get(object.id); }) - .then((o) => { + .then(o => { object1 = o; - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(object.id); }) - .then((o) => { + .then(o => { object2 = o; - assert.equal(object1.get("test"), "foo"); - assert.equal(object2.get("test"), "foo"); - object2.unset("test"); + assert.equal(object1.get('test'), 'foo'); + assert.equal(object2.get('test'), 'foo'); + object2.unset('test'); return object2.save(); }) - .then((o) => { + .then(o => { object2 = o; return object1.fetch(); }) - .then((o) => { + .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"); + 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) => { - const object = new TestObject({ foo: "bar" }); + it('does not change createdAt', done => { + const object = new TestObject({ foo: 'bar' }); object .save() .then(() => { @@ -245,14 +245,14 @@ describe("Parse Object", () => { objectAgain.id = object.id; return objectAgain.fetch(); }) - .then((o) => { + .then(o => { assert.equal(o.createdAt.getTime(), object.createdAt.getTime()); done(); }); }); - it("exposes createdAt and updatedAt as top level properties", (done) => { - const object = new TestObject({ foo: "bar" }); + it('exposes createdAt and updatedAt as top level properties', done => { + const object = new TestObject({ foo: 'bar' }); object.save().then(() => { assert(object.updatedAt); assert(object.createdAt); @@ -260,9 +260,9 @@ 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" }); + const object = new TestObject({ foo: 'bar' }); object.save().then(() => { const end = new Date(); const startDiff = Math.abs(start.getTime() - object.createdAt.getTime()); @@ -275,72 +275,72 @@ describe("Parse Object", () => { }); }); - it("can increment nested fields", async () => { + it('can increment nested fields', async () => { const obj = new TestObject(); - obj.set("objectField", { number: 5 }); - assert.equal(obj.get("objectField").number, 5); + obj.set('objectField', { number: 5 }); + assert.equal(obj.get('objectField').number, 5); await obj.save(); - obj.increment("objectField.number", 15); - assert.equal(obj.get("objectField").number, 20); + obj.increment('objectField.number', 15); + assert.equal(obj.get('objectField').number, 20); await obj.save(); - assert.equal(obj.get("objectField").number, 20); + assert.equal(obj.get('objectField').number, 20); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, 20); + assert.equal(result.get('objectField').number, 20); }); - it("can increment nested field and retain full object", async () => { - const obj = new Parse.Object("TestIncrementObject"); - obj.set("objectField", { number: 5, letter: "a" }); - assert.equal(obj.get("objectField").number, 5); - assert.equal(obj.get("objectField").letter, "a"); + it('can increment nested field and retain full object', async () => { + const obj = new Parse.Object('TestIncrementObject'); + obj.set('objectField', { number: 5, letter: 'a' }); + 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", + letter: 'a', }); - obj.increment("objectField.number", 15); + obj.increment('objectField.number', 15); assert.deepStrictEqual(obj.attributes.objectField, { number: 20, - letter: "a", + letter: 'a', }); assert.deepStrictEqual(obj.attributes.objectField, { number: 20, - letter: "a", + letter: 'a', }); - assert.equal(obj.get("objectField").number, 20); - assert.equal(obj.get("objectField").letter, "a"); + assert.equal(obj.get('objectField').number, 20); + assert.equal(obj.get('objectField').letter, 'a'); await obj.save(); - assert.equal(obj.get("objectField").number, 20); - assert.equal(obj.get("objectField").letter, "a"); + assert.equal(obj.get('objectField').number, 20); + assert.equal(obj.get('objectField').letter, 'a'); assert.deepStrictEqual(obj.attributes.objectField, { number: 20, - letter: "a", + letter: 'a', }); - const query = new Parse.Query("TestIncrementObject"); + 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.equal(result.get('objectField').number, 20); + assert.equal(result.get('objectField').letter, 'a'); assert.deepStrictEqual(result.attributes.objectField, { number: 20, - letter: "a", + letter: 'a', }); }); - it("can increment non existing field", async () => { + it('can increment non existing field', async () => { const obj = new TestObject(); - obj.set("objectField", { number: 5 }); + obj.set('objectField', { number: 5 }); await obj.save(); - obj.increment("objectField.unknown", 15); - assert.deepEqual(obj.get("objectField"), { + obj.increment('objectField.unknown', 15); + assert.deepEqual(obj.get('objectField'), { number: 5, unknown: 15, }); @@ -348,384 +348,384 @@ describe("Parse Object", () => { const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, 5); - assert.equal(result.get("objectField").unknown, 15); + assert.equal(result.get('objectField').number, 5); + assert.equal(result.get('objectField').unknown, 15); }); - it("can increment nested fields two levels", async () => { + it('can increment nested fields two levels', async () => { const obj = new TestObject(); - obj.set("objectField", { foo: { bar: 5 } }); - assert.equal(obj.get("objectField").foo.bar, 5); + obj.set('objectField', { foo: { bar: 5 } }); + assert.equal(obj.get('objectField').foo.bar, 5); await obj.save(); - obj.increment("objectField.foo.bar", 15); - assert.equal(obj.get("objectField").foo.bar, 20); + obj.increment('objectField.foo.bar', 15); + assert.equal(obj.get('objectField').foo.bar, 20); await obj.save(); - assert.equal(obj.get("objectField").foo.bar, 20); + assert.equal(obj.get('objectField').foo.bar, 20); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").foo.bar, 20); + assert.equal(result.get('objectField').foo.bar, 20); }); - it("can increment nested fields without object", async () => { + it('can increment nested fields without object', async () => { const obj = new TestObject(); - obj.set("hello", "world"); + obj.set('hello', 'world'); await obj.save(); - obj.increment("hello.dot", 15); + obj.increment('hello.dot', 15); try { await obj.save(); assert.equal(false, true); } catch (error) { assert.equal( error.message, - "schema mismatch for TestObject.hello; expected String but got Object" + 'schema mismatch for TestObject.hello; expected String but got Object' ); } }); - it("can set nested fields", async () => { + it('can set nested fields', async () => { const obj = new TestObject({ objectField: { number: 5 } }); - assert.equal(obj.get("objectField").number, 5); + assert.equal(obj.get('objectField').number, 5); await obj.save(); - assert.equal(obj.get("objectField").number, 5); - obj.set("objectField.number", 20); - assert.equal(obj.get("objectField").number, 20); + assert.equal(obj.get('objectField').number, 5); + obj.set('objectField.number', 20); + assert.equal(obj.get('objectField').number, 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, 20); + assert.equal(result.get('objectField').number, 20); }); - it("can set non existing fields", async () => { + it('can set non existing fields', async () => { const obj = new TestObject(); - obj.set("objectField", { number: 5 }); + obj.set('objectField', { number: 5 }); await obj.save(); - obj.set("objectField.unknown", 20); + obj.set('objectField.unknown', 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, 5); - assert.equal(result.get("objectField").unknown, 20); + assert.equal(result.get('objectField').number, 5); + assert.equal(result.get('objectField').unknown, 20); }); - it("ignore set nested fields on new object", async () => { + it('ignore set nested fields on new object', async () => { const obj = new TestObject(); - obj.set("objectField.number", 5); + obj.set('objectField.number', 5); assert.deepEqual(obj._getPendingOps()[0], {}); - assert.equal(obj.get("objectField"), undefined); + assert.equal(obj.get('objectField'), undefined); await obj.save(); - assert.equal(obj.get("objectField"), undefined); + assert.equal(obj.get('objectField'), undefined); }); - it("can set nested fields two levels", async () => { + it('can set nested fields two levels', async () => { const obj = new TestObject({ objectField: { foo: { bar: 5 } } }); - assert.equal(obj.get("objectField").foo.bar, 5); + assert.equal(obj.get('objectField').foo.bar, 5); await obj.save(); - assert.equal(obj.get("objectField").foo.bar, 5); - obj.set("objectField.foo.bar", 20); - assert.equal(obj.get("objectField").foo.bar, 20); + assert.equal(obj.get('objectField').foo.bar, 5); + obj.set('objectField.foo.bar', 20); + assert.equal(obj.get('objectField').foo.bar, 20); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").foo.bar, 20); + assert.equal(result.get('objectField').foo.bar, 20); }); - it("can unset nested fields", async () => { + it('can unset nested fields', async () => { const obj = new TestObject({ objectField: { number: 5, - string: "hello", + string: 'hello', }, }); await obj.save(); - obj.unset("objectField.number"); - assert.equal(obj.get("objectField").number, undefined); - assert.equal(obj.get("objectField").string, "hello"); + obj.unset('objectField.number'); + assert.equal(obj.get('objectField').number, undefined); + assert.equal(obj.get('objectField').string, 'hello'); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, undefined); - assert.equal(result.get("objectField").string, "hello"); + assert.equal(result.get('objectField').number, undefined); + assert.equal(result.get('objectField').string, 'hello'); }); - it("can unset nested fields two levels", async () => { + it('can unset nested fields two levels', async () => { const obj = new TestObject({ objectField: { foo: { bar: 5, }, - string: "hello", + string: 'hello', }, }); await obj.save(); - obj.unset("objectField.foo.bar"); - assert.equal(obj.get("objectField").foo.bar, undefined); - assert.equal(obj.get("objectField").string, "hello"); + obj.unset('objectField.foo.bar'); + assert.equal(obj.get('objectField').foo.bar, undefined); + assert.equal(obj.get('objectField').string, 'hello'); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").foo.bar, undefined); - assert.equal(result.get("objectField").string, "hello"); + assert.equal(result.get('objectField').foo.bar, undefined); + assert.equal(result.get('objectField').string, 'hello'); }); - it("can unset non existing fields", async () => { + it('can unset non existing fields', async () => { const obj = new TestObject(); - obj.set("objectField", { number: 5 }); + obj.set('objectField', { number: 5 }); await obj.save(); - obj.unset("objectField.unknown"); + obj.unset('objectField.unknown'); await obj.save(); const query = new Parse.Query(TestObject); const result = await query.get(obj.id); - assert.equal(result.get("objectField").number, 5); - assert.equal(result.get("objectField").unknown, undefined); + assert.equal(result.get('objectField').number, 5); + 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.set('foo', null); obj.save().then(() => { - assert.equal(obj.get("foo"), null); + assert.equal(obj.get('foo'), null); done(); }); }); - it("can set boolean fields", (done) => { + it('can set boolean fields', done => { const obj = new TestObject(); - obj.set("yes", true); - obj.set("no", false); + obj.set('yes', true); + obj.set('no', false); obj.save().then(() => { - assert.equal(obj.get("yes"), true); - assert.equal(obj.get("no"), false); + assert.equal(obj.get('yes'), true); + assert.equal(obj.get('no'), false); done(); }); }); - 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.set('when', new Date(Date.parse(null))); obj.save().catch(() => { done(); }); }); - it("cannot create invalid class names", (done) => { - const item = new Parse.Object("Foo^Bar"); + 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) => { - const item = new Parse.Object("Item"); - assert(!item.set({ "foo^bar": "baz" })); - item.save({ "foo^bar": "baz" }).catch((e) => { + 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 => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); }); - it("cannot use invalid key names in multiple sets", () => { - const item = new Parse.Object("Item"); + it('cannot use invalid key names in multiple sets', () => { + const item = new Parse.Object('Item'); assert( !item.set({ - foobar: "baz", - "foo^bar": "baz", + foobar: 'baz', + 'foo^bar': 'baz', }) ); - assert(!item.get("foobar")); + assert(!item.get('foobar')); }); - it("can unset fields", (done) => { - const simple = new Parse.Object("SimpleObject"); + it('can unset fields', done => { + const simple = new Parse.Object('SimpleObject'); simple - .save({ foo: "bar" }) + .save({ foo: 'bar' }) .then(() => { - simple.unset("foo"); - assert(!simple.has("foo")); - assert(simple.dirty("foo")); + 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.has('foo')); + assert(!simple.dirty('foo')); assert(!simple.dirty()); - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert(!s.has("foo")); + .then(s => { + assert(!s.has('foo')); done(); }); }); - it("can delete fields before the first save", (done) => { - const simple = new Parse.Object("SimpleObject"); - simple.set("foo", "bar"); - simple.unset("foo"); + it('can delete fields before the first save', done => { + const simple = new Parse.Object('SimpleObject'); + simple.set('foo', 'bar'); + simple.unset('foo'); - assert(!simple.has("foo")); - assert(simple.dirty("foo")); + assert(!simple.has('foo')); + assert(simple.dirty('foo')); assert(simple.dirty()); simple .save() .then(() => { - assert(!simple.has("foo")); - assert(!simple.dirty("foo")); + assert(!simple.has('foo')); + assert(!simple.dirty('foo')); assert(!simple.dirty()); - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert(!s.has("foo")); + .then(s => { + assert(!s.has('foo')); done(); }); }); - it("can delete pointers", (done) => { - const simple = new Parse.Object("SimpleObject"); - const child = new Parse.Object("Child"); + 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")); + 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.has('child')); + assert(!simple.dirty('child')); assert(!simple.dirty()); - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert(!s.has("foo")); + .then(s => { + assert(!s.has('foo')); done(); }); }); - it("clears deleted keys", (done) => { - const simple = new Parse.Object("SimpleObject"); - simple.set("foo", "bar"); - simple.unset("foo"); + 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"); + simple.set('foo', 'baz'); return simple.save(); }) .then(() => { - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert.equal(s.get("foo"), "baz"); + .then(s => { + assert.equal(s.get('foo'), 'baz'); done(); }); }); - it("can set keys after deleting them", (done) => { - const simple = new Parse.Object("SimpleObject"); - simple.set("foo", "bar"); + 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"); + simple.unset('foo'); + simple.set('foo', 'baz'); return simple.save(); }) .then(() => { - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert.equal(s.get("foo"), "baz"); + .then(s => { + assert.equal(s.get('foo'), 'baz'); done(); }); }); - it("can increment fields", (done) => { - const simple = new Parse.Object("SimpleObject"); + 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")); + 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.equal(simple.get('count'), 6); + assert(!simple.dirty('count')); assert(!simple.dirty()); - const query = new Parse.Query("SimpleObject"); + const query = new Parse.Query('SimpleObject'); return query.get(simple.id); }) - .then((s) => { - assert.equal(s.get("count"), 6); + .then(s => { + assert.equal(s.get('count'), 6); done(); }); }); - it("can set the object id", () => { + it('can set the object id', () => { const object = new TestObject(); - object.set("objectId", "foo"); - assert.equal(object.id, "foo"); - object.set("id", "bar"); - assert.equal(object.id, "bar"); + object.set('objectId', 'foo'); + assert.equal(object.id, 'foo'); + object.set('id', 'bar'); + 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"); + object.set('cat', 'goog'); + object.set('dog', 'bad'); object.save().then(() => { assert(!object.dirty()); - assert(!object.dirty("cat")); - assert(!object.dirty("dog")); + assert(!object.dirty('cat')); + assert(!object.dirty('dog')); - object.set("dog", "okay"); + object.set('dog', 'okay'); assert(object.dirty()); - assert(!object.dirty("cat")); - assert(object.dirty("dog")); + assert(!object.dirty('cat')); + assert(object.dirty('dog')); done(); }); }); - it("can collect dirty keys", (done) => { + it('can collect dirty keys', done => { const object = new TestObject(); - object.set("dog", "good"); - object.set("cat", "bad"); + object.set('dog', 'good'); + object.set('cat', 'bad'); assert(object.dirty()); let dirtyKeys = object.dirtyKeys(); assert.equal(dirtyKeys.length, 2); - assert(dirtyKeys.indexOf("dog") > -1); - assert(dirtyKeys.indexOf("cat") > -1); + assert(dirtyKeys.indexOf('dog') > -1); + assert(dirtyKeys.indexOf('cat') > -1); object .save() @@ -733,56 +733,56 @@ describe("Parse Object", () => { assert(!object.dirty()); dirtyKeys = object.dirtyKeys(); assert.equal(dirtyKeys.length, 0); - assert(dirtyKeys.indexOf("dog") < 0); - assert(dirtyKeys.indexOf("cat") < 0); + assert(dirtyKeys.indexOf('dog') < 0); + assert(dirtyKeys.indexOf('cat') < 0); - object.unset("cat"); + object.unset('cat'); assert(object.dirty()); dirtyKeys = object.dirtyKeys(); assert.equal(dirtyKeys.length, 1); - assert(dirtyKeys.indexOf("dog") < 0); - assert(dirtyKeys.indexOf("cat") > -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); + 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); + assert(dirtyKeys.indexOf('dog') < 0); + assert(dirtyKeys.indexOf('cat') < 0); done(); }); }); - it("can set ops directly", (done) => { - const object = new Parse.Object("TestObject"); - object.set({ cat: "good", dog: "bad" }); + 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"); + assert.equal(object.get('cat'), 'good'); - object.set({ x: { __op: "Increment", amount: 5 } }); - assert.equal(object.get("x"), 5); + 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); + 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({ 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); + object.set({ cat: { __op: 'Delete' } }); + assert(!object.has('cat')); + assert(object.op('cat') instanceof Parse.Op.Unset); - const Related = Parse.Object.extend("RelatedObject"); + const Related = Parse.Object.extend('RelatedObject'); const relatedObjects = []; for (let i = 0; i < 5; i++) { relatedObjects.push(new Related({ i: i })); @@ -791,31 +791,31 @@ describe("Parse Object", () => { .then(() => { object.set({ relation: { - __op: "Batch", + __op: 'Batch', ops: [ { - __op: "AddRelation", + __op: 'AddRelation', objects: [relatedObjects[0], relatedObjects[1]], }, { - __op: "AddRelation", + __op: 'AddRelation', objects: [relatedObjects[2], relatedObjects[3]], }, ], }, }); - let relation = object.op("relation"); + let relation = object.op('relation'); assert(relation instanceof Parse.Op.Relation); assert.equal(relation.relationsToAdd.length, 4); object.set({ relation: { - __op: "RemoveRelation", + __op: 'RemoveRelation', objects: [relatedObjects[1], relatedObjects[4]], }, }); - relation = object.op("relation"); + relation = object.op('relation'); assert(relation instanceof Parse.Op.Relation); assert.equal(relation.relationsToAdd.length, 3); assert.equal(relation.relationsToRemove.length, 2); @@ -826,195 +826,195 @@ describe("Parse Object", () => { .catch(done.fail); }); - it("can repeatedly unset old attributes", (done) => { + it('can repeatedly unset old attributes', done => { const obj = new TestObject(); - obj.set("x", 3); + obj.set('x', 3); obj .save() .then(() => { - obj.unset("x"); - obj.unset("x"); + obj.unset('x'); + obj.unset('x'); return obj.save(); }) .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 5); + obj.unset('x'); + obj.unset('x'); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.unset('x'); + obj.unset('x'); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 3); obj .save() .then(() => { - obj.unset("x"); + obj.unset('x'); obj.clear(); return obj.save(); }) .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 5); + obj.unset('x'); obj.clear(); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.unset('x'); obj.clear(); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 3); obj .save() .then(() => { obj.clear(); - obj.unset("x"); + obj.unset('x'); return obj.save(); }) .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 5); obj.clear(); - obj.unset("x"); + obj.unset('x'); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.unset('x'); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 3); obj .save() .then(() => { @@ -1023,101 +1023,101 @@ describe("Parse Object", () => { return obj.save(); }) .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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.set('x', 5); obj.clear(); obj.clear(); obj .save() .then(() => { - assert.equal(obj.has("x"), false); - assert.equal(obj.get("x"), undefined); + 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); + .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); + 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); + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); done(); }); }); - it("can save children in an array", (done) => { - const Parent = Parse.Object.extend("Parent"); - const Child = Parse.Object.extend("Child"); + it('can save children in an array', done => { + const Parent = Parse.Object.extend('Parent'); + const Child = Parse.Object.extend('Child'); const child1 = new Child(); const child2 = new Child(); const parent = new Parent(); - child1.set("name", "jaime"); - child1.set("house", "lannister"); - child2.set("name", "cersei"); - child2.set("house", "lannister"); - parent.set("children", [child1, child2]); + child1.set('name', 'jaime'); + child1.set('house', 'lannister'); + child2.set('name', 'cersei'); + 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"); + query.equalTo('house', 'lannister'); + query.ascending('name'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "cersei"); - assert.equal(results[1].get("name"), "jaime"); + 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) => { - const Parent = Parse.Object.extend("Parent"); - const Child = Parse.Object.extend("Child"); + it('can skip cascade saving as per request', async done => { + const Parent = Parse.Object.extend('Parent'); + const Child = Parse.Object.extend('Child'); const parent = new Parent(); const child1 = new Child(); const child2 = new Child(); const child3 = new Child(); - child1.set("name", "rob"); - child2.set("name", "sansa"); - child3.set("name", "john"); - parent.set("children", [child1, child2]); - parent.set("bastard", child3); + child1.set('name', 'rob'); + child2.set('name', 'sansa'); + child3.set('name', 'john'); + parent.set('children', [child1, child2]); + parent.set('bastard', child3); expect(parent.save).toThrow(); let results = await new Parse.Query(Child).find(); @@ -1127,22 +1127,22 @@ describe("Parse Object", () => { results = await new Parse.Query(Child).find(); assert.equal(results.length, 3); - parent.set("dead", true); - child1.set("dead", true); + parent.set('dead', true); + child1.set('dead', true); await parent.save(null); - const rob = await new Parse.Query(Child).equalTo("name", "rob").first(); - expect(rob.get("dead")).toBe(true); + const rob = await new Parse.Query(Child).equalTo('name', 'rob').first(); + expect(rob.get('dead')).toBe(true); - parent.set("lastname", "stark"); - child3.set("lastname", "stark"); + parent.set('lastname', 'stark'); + child3.set('lastname', 'stark'); await parent.save(null, { cascadeSave: false }); - const john = await new Parse.Query(Child).doesNotExist("lastname").first(); - expect(john.get("lastname")).toBeUndefined(); + const john = await new Parse.Query(Child).doesNotExist('lastname').first(); + expect(john.get('lastname')).toBeUndefined(); 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; @@ -1152,34 +1152,34 @@ describe("Parse Object", () => { return; } - const query = new Parse.Query("TestObject"); - query.equalTo("test", "doublesave"); - query.find().then((results) => { + const query = new Parse.Query('TestObject'); + query.equalTo('test', 'doublesave'); + query.find().then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("cat"), "meow"); - assert.equal(results[0].get("dog"), "bark"); + 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); + 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.set('number', 1); object .save() .then(() => { other = new TestObject(); - other.set("number", "two"); + other.set('number', 'two'); return other.save(); }) - .catch((e) => { + .catch(e => { assert.equal(e.code, Parse.Error.INCORRECT_TYPE); - other.set("number", 2); + other.set('number', 2); return other.save(); }) .then(() => { @@ -1187,65 +1187,65 @@ describe("Parse Object", () => { }); }); - 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")); + object.set({ content: 'x' }); + assert(object.dirty('content')); return object.fetch(); }) .then(() => { - assert(!object.dirty("content")); + assert(!object.dirty('content')); done(); }); }); - it("can add objects to an array", (done) => { - const child = new Parse.Object("Person"); - const parent = new Parse.Object("Person"); + 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); + parent.add('children', child); return parent.save(); }) .then(() => { - const query = new Parse.Query("Person"); + const query = new Parse.Query('Person'); return query.get(parent.id); }) - .then((p) => { - assert.equal(p.get("children")[0].id, child.id); + .then(p => { + assert.equal(p.get('children')[0].id, child.id); 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"); + 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); + .then(children => { + parent.addAll('children', children); return parent.save(); }) .then(() => { - const query = new Parse.Query("Person"); + 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); + .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(() => { + object.save({ foo: 'bar' }).then(() => { const json = object.toJSON(); assert(json.foo); assert(json.objectId); @@ -1255,9 +1255,9 @@ describe("Parse Object", () => { }); }); - it("can convert unsaved objects to json", () => { + it('can convert unsaved objects to json', () => { const object = new TestObject(); - object.set({ foo: "bar" }); + object.set({ foo: 'bar' }); const json = object.toJSON(); assert(json.foo); assert(!json.objectId); @@ -1265,54 +1265,54 @@ 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); + 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); + 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) => { + .then(objects => { const container = new TestObject(); - container.addAll("array", objects); - assert.equal(container.get("array").length, 2); + container.addAll('array', objects); + assert.equal(container.get('array').length, 2); return container.save(); }) - .then((container) => { + .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"; + o3.id = 'there_is_no_such_object'; - container.removeAll("array", [o1, o2, o3]); - assert.equal(container.get("array").length, 0); + 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.set('time', 'adventure'); object .save() .then(() => { @@ -1321,26 +1321,26 @@ describe("Parse Object", () => { again.id = object.id; return again.fetch(); }) - .then((again) => { - assert.equal(again.get("time"), "adventure"); + .then(again => { + assert.equal(again.get('time'), 'adventure'); return again.destroy(); }) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("objectId", object.id); + query.equalTo('objectId', object.id); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 0); done(); }); }); - it("fails validation with a promise", (done) => { - const PickyEater = Parse.Object.extend("PickyEater", { + it('fails validation with a promise', done => { + const PickyEater = Parse.Object.extend('PickyEater', { validate: function (attrs) { - if (attrs.meal === "tomatoes") { - return "Ew. Gross."; + if (attrs.meal === 'tomatoes') { + return 'Ew. Gross.'; } return Parse.Object.prototype.validate.apply(this, arguments); }, @@ -1348,46 +1348,46 @@ describe("Parse Object", () => { const bryan = new PickyEater(); bryan - .save({ meal: "burrito" }) + .save({ meal: 'burrito' }) .then(() => { - return bryan.save({ meal: "tomatoes" }); + return bryan.save({ meal: 'tomatoes' }); }) - .catch((e) => { - assert.equal(e, "Ew. Gross."); + .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.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="); + .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(() => { @@ -1397,13 +1397,13 @@ describe("Parse Object", () => { const query = new Parse.Query(TestObject); return query.get(o.id); }) - .catch((e) => { + .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(); @@ -1414,36 +1414,36 @@ describe("Parse Object", () => { }) .then(() => { const query = new Parse.Query(TestObject); - query.containedIn("objectId", [objects[0].id, objects[20].id]); + query.containedIn('objectId', [objects[0].id, objects[20].id]); return query.find(); }) - .then((results) => { + .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) => { + o.id = 'fakeobject'; + 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"; + objects[0].id = 'fakeobject'; return Parse.Object.destroyAll(objects); }) - .catch((e) => { + .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); @@ -1452,17 +1452,17 @@ describe("Parse Object", () => { }); }); - 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"; + objects[19].id = 'fakeobject'; return Parse.Object.destroyAll(objects); }) - .catch((e) => { + .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); @@ -1471,17 +1471,17 @@ describe("Parse Object", () => { }); }); - 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"; + objects[20].id = 'fakeobject'; return Parse.Object.destroyAll(objects); }) - .catch((e) => { + .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); @@ -1490,19 +1490,19 @@ describe("Parse Object", () => { }); }); - 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"; + objects[0].id = 'fakeobject'; + objects[19].id = 'fakeobject'; + objects[20].id = 'fakeobject'; return Parse.Object.destroyAll(objects); }) - .catch((e) => { + .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); @@ -1515,64 +1515,64 @@ describe("Parse Object", () => { }); }); - it("can fetchAll", (done) => { + it('can fetchAll', done => { const numItems = 11; const container = new Container(); const items = []; for (let i = 0; i < numItems; i++) { const item = new Item(); - item.set("x", i); + item.set('x', i); items.push(item); } Parse.Object.saveAll(items) .then(() => { - container.set("items", items); + 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"); + .then(containerAgain => { + const itemsAgain = containerAgain.get('items'); assert.equal(itemsAgain.length, numItems); itemsAgain.forEach((item, i) => { const newValue = i * 2; - item.set("x", newValue); + item.set('x', newValue); }); return Parse.Object.saveAll(itemsAgain); }) .then(() => { return Parse.Object.fetchAll(items); }) - .then((itemsAgain) => { + .then(itemsAgain => { assert.equal(itemsAgain.length, numItems); itemsAgain.forEach((item, i) => { - assert.equal(item.get("x"), i * 2); + assert.equal(item.get('x'), i * 2); }); 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.set('x', 7); object .save() .then(() => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((result) => { + .then(result => { updated = result; - updated.set("x", 11); + updated.set('x', 11); return updated.save(); }) .then(() => { @@ -1585,40 +1585,40 @@ describe("Parse Object", () => { }); }); - it("fails fetchAll on multiple classes", () => { + it('fails fetchAll on multiple classes', () => { const container = new Container(); - container.set("item", new Item()); - container.set("subcontainer", 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"); + .then(containerAgain => { + const subContainerAgain = containerAgain.get('subcontainer'); + const itemAgain = containerAgain.get('item'); const multiClassArray = [subContainerAgain, itemAgain]; return Parse.Object.fetchAll(multiClassArray); }) - .catch((e) => { + .catch(e => { assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); }); }); - it("fails fetchAll on unsaved object", () => { + 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++) { const item = new Item(); - item.set("x", i); + item.set('x', i); items.push(item); } Parse.Object.saveAll(items) @@ -1626,27 +1626,27 @@ describe("Parse Object", () => { const query = new Parse.Query(Item); return query.get(items[0].id); }) - .then((objectToDelete) => { + .then(objectToDelete => { return objectToDelete.destroy(); }) - .then((deletedObject) => { + .then(deletedObject => { const nonExistentObject = new Item({ objectId: deletedObject.id }); const nonExistentObjectArray = [nonExistentObject, items[1]]; return Parse.Object.fetchAll(nonExistentObjectArray); }) - .catch((e) => { + .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.set('username', 'asdf'); + user.set('password', 'zxcv'); + user.set('foo', 'bar'); user .signUp() .then(() => { @@ -1654,17 +1654,17 @@ describe("Parse Object", () => { const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((userAgain) => { + .then(userAgain => { user = userAgain; sameUser = new Parse.User(); - sameUser.set("username", "asdf"); - sameUser.set("password", "zxcv"); + sameUser.set('username', 'asdf'); + sameUser.set('password', 'zxcv'); return sameUser.logIn(); }) .then(() => { assert(!user.getSessionToken()); assert(sameUser.getSessionToken()); - sameUser.set("baz", "qux"); + sameUser.set('baz', 'qux'); return sameUser.save(); }) .then(() => { @@ -1685,8 +1685,8 @@ describe("Parse Object", () => { .catch(done.fail); }); - it("can fetchAllIfNeededWithInclude", async () => { - const pointer = new TestObject({ foo: "bar" }); + it('can fetchAllIfNeededWithInclude', async () => { + const pointer = new TestObject({ foo: 'bar' }); const item1 = new Item({ x: 1 }); const item2 = new Item({ x: 2, pointer }); const items = [item1, item2]; @@ -1694,15 +1694,15 @@ describe("Parse Object", () => { await Parse.Object.saveAll(items); const container = new Container(); - container.set("items", items); + container.set('items', items); await container.save(); const query = new Parse.Query(Container); const containerAgain = await query.get(container.id); // Fetch objects with no data - const itemsAgain = containerAgain.get("items"); - const item1Again = itemsAgain[0].set("x", 100); + const itemsAgain = containerAgain.get('items'); + const item1Again = itemsAgain[0].set('x', 100); const item2Again = itemsAgain[1]; // Override item1 in database, this shouldn't fetch @@ -1710,313 +1710,292 @@ describe("Parse Object", () => { const fetchedItems = await Parse.Object.fetchAllIfNeededWithInclude( [item1, item2Again], - ["pointer"] + ['pointer'] ); assert.equal(fetchedItems.length, items.length); - assert.equal(fetchedItems[0].get("x"), 1); - assert.equal(fetchedItems[1].get("x"), 2); // item2Again should update - assert.equal(fetchedItems[1].get("pointer").id, pointer.id); - assert.equal(fetchedItems[1].get("pointer").get("foo"), "bar"); + assert.equal(fetchedItems[0].get('x'), 1); + assert.equal(fetchedItems[1].get('x'), 2); // item2Again should update + assert.equal(fetchedItems[1].get('pointer').id, pointer.id); + 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 = []; for (let i = 0; i < numItems; i++) { const item = new Item(); - item.set("x", i); + item.set('x', i); items.push(item); } Parse.Object.saveAll(items) .then(() => { - container.set("items", items); + 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"); + .then(containerAgain => { + const itemsAgain = containerAgain.get('items'); itemsAgain.forEach((item, i) => { - item.set("x", i * 2); + item.set('x', i * 2); }); return Parse.Object.saveAll(itemsAgain); }) .then(() => { return Parse.Object.fetchAllIfNeeded(items); }) - .then((fetchedItems) => { + .then(fetchedItems => { assert.equal(fetchedItems.length, numItems); fetchedItems.forEach((item, i) => { - assert.equal(item.get("x"), i); + assert.equal(item.get('x'), i); }); 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(); }); }); - it("fails fetchAllIfNeeded on multiple classes", () => { + it('fails fetchAllIfNeeded on multiple classes', () => { const container = new Container(); - container.set("item", new Item()); - container.set("subcontainer", 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"); + .then(containerAgain => { + const subContainerAgain = containerAgain.get('subcontainer'); + const itemAgain = containerAgain.get('item'); const multiClassArray = [subContainerAgain, itemAgain]; return Parse.Object.fetchAllIfNeeded(multiClassArray); }) - .catch((e) => { + .catch(e => { assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); }); }); - it("can rewrite the User classname", (done) => { - assert.equal(Parse.CoreManager.get("PERFORM_USER_REWRITE"), true); + 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"); + assert.equal(User1.className, '_User'); Parse.User.allowCustomUserClass(true); - assert.equal(Parse.CoreManager.get("PERFORM_USER_REWRITE"), false); + assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), false); const User2 = Parse.Object.extend({ - className: "User", + className: 'User', }); - assert.equal(User2.className, "User"); + assert.equal(User2.className, 'User'); Parse.User.allowCustomUserClass(false); - assert.equal(Parse.CoreManager.get("PERFORM_USER_REWRITE"), true); + assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), true); const user = new User2(); - user.set("name", "Me"); + user.set('name', 'Me'); user .save({ height: 181 }) .then(() => { - assert.equal(user.get("name"), "Me"); - assert.equal(user.get("height"), 181); + 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); + assert.equal(user.className, 'User'); + assert.equal(user.get('name'), 'Me'); + assert.equal(user.get('height'), 181); done(); }); }); - it("can create objects without data", (done) => { - const t1 = new TestObject({ test: "test" }); + 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"); + .then(t2 => { + assert.equal(t2.get('test'), 'test'); const t3 = TestObject.createWithoutData(t2.id); - t3.set("test", "not test"); + t3.set('test', 'not test'); return t3.fetch(); }) - .then((t3) => { - assert.equal(t3.get("test"), "test"); + .then(t3 => { + assert.equal(t3.get('test'), 'test'); done(); }); }); - it("can fetchWithInclude", async () => { + it('can fetchWithInclude', async () => { const parent = new TestObject(); const child = new TestObject(); - child.set("field", "isChild"); - parent.set("child", child); + child.set('field', 'isChild'); + parent.set('child', child); await parent.save(); const obj1 = TestObject.createWithoutData(parent.id); - const fetchedObj1 = await obj1.fetchWithInclude("child"); - assert.equal(obj1.get("child").get("field"), "isChild"); - assert.equal(fetchedObj1.get("child").get("field"), "isChild"); + const fetchedObj1 = await obj1.fetchWithInclude('child'); + assert.equal(obj1.get('child').get('field'), 'isChild'); + assert.equal(fetchedObj1.get('child').get('field'), 'isChild'); const obj2 = TestObject.createWithoutData(parent.id); - const fetchedObj2 = await obj2.fetchWithInclude(["child"]); - assert.equal(obj2.get("child").get("field"), "isChild"); - assert.equal(fetchedObj2.get("child").get("field"), "isChild"); + const fetchedObj2 = await obj2.fetchWithInclude(['child']); + assert.equal(obj2.get('child').get('field'), 'isChild'); + assert.equal(fetchedObj2.get('child').get('field'), 'isChild'); const obj3 = TestObject.createWithoutData(parent.id); - const fetchedObj3 = await obj3.fetchWithInclude([["child"]]); - assert.equal(obj3.get("child").get("field"), "isChild"); - assert.equal(fetchedObj3.get("child").get("field"), "isChild"); + const fetchedObj3 = await obj3.fetchWithInclude([['child']]); + assert.equal(obj3.get('child').get('field'), 'isChild'); + assert.equal(fetchedObj3.get('child').get('field'), 'isChild'); }); - it("can fetchWithInclude dot notation", async () => { + it('can fetchWithInclude dot notation', async () => { const parent = new TestObject(); const child = new TestObject(); const grandchild = new TestObject(); - grandchild.set("field", "isGrandchild"); - child.set("grandchild", grandchild); - parent.set("child", child); + grandchild.set('field', 'isGrandchild'); + child.set('grandchild', grandchild); + parent.set('child', child); await Parse.Object.saveAll([parent, child, grandchild]); const obj1 = TestObject.createWithoutData(parent.id); - await obj1.fetchWithInclude("child.grandchild"); - assert.equal( - obj1.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + await obj1.fetchWithInclude('child.grandchild'); + assert.equal(obj1.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj2 = TestObject.createWithoutData(parent.id); - await obj2.fetchWithInclude(["child.grandchild"]); - assert.equal( - obj2.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + await obj2.fetchWithInclude(['child.grandchild']); + assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj3 = TestObject.createWithoutData(parent.id); - await obj3.fetchWithInclude([["child.grandchild"]]); - assert.equal( - obj3.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + await obj3.fetchWithInclude([['child.grandchild']]); + assert.equal(obj3.get('child').get('grandchild').get('field'), 'isGrandchild'); }); - it("can fetchAllWithInclude", async () => { + it('can fetchAllWithInclude', async () => { const parent = new TestObject(); const child = new TestObject(); - child.set("field", "isChild"); - parent.set("child", child); + child.set('field', 'isChild'); + parent.set('child', child); await parent.save(); const obj1 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj1], "child"); - assert.equal(obj1.get("child").get("field"), "isChild"); + await Parse.Object.fetchAllWithInclude([obj1], 'child'); + assert.equal(obj1.get('child').get('field'), 'isChild'); const obj2 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj2], ["child"]); - assert.equal(obj2.get("child").get("field"), "isChild"); + await Parse.Object.fetchAllWithInclude([obj2], ['child']); + assert.equal(obj2.get('child').get('field'), 'isChild'); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [["child"]]); - assert.equal(obj3.get("child").get("field"), "isChild"); + await Parse.Object.fetchAllWithInclude([obj3], [['child']]); + assert.equal(obj3.get('child').get('field'), 'isChild'); }); - it("can fetchAllWithInclude dot notation", async () => { + it('can fetchAllWithInclude dot notation', async () => { const parent = new TestObject(); const child = new TestObject(); const grandchild = new TestObject(); - grandchild.set("field", "isGrandchild"); - child.set("grandchild", grandchild); - parent.set("child", child); + grandchild.set('field', 'isGrandchild'); + child.set('grandchild', grandchild); + parent.set('child', child); await Parse.Object.saveAll([parent, child, grandchild]); const obj1 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj1], "child.grandchild"); - assert.equal( - obj1.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + await Parse.Object.fetchAllWithInclude([obj1], 'child.grandchild'); + assert.equal(obj1.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj2 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj2], ["child.grandchild"]); - assert.equal( - obj2.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + await Parse.Object.fetchAllWithInclude([obj2], ['child.grandchild']); + assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [["child.grandchild"]]); - assert.equal( - obj3.get("child").get("grandchild").get("field"), - "isGrandchild" - ); + 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) => { - const LimitedObject = Parse.Object.extend("LimitedObject"); + it('fires errors when readonly attributes are changed', done => { + const LimitedObject = Parse.Object.extend('LimitedObject'); LimitedObject.readOnlyAttributes = function () { - return ["immutable"]; + return ['immutable']; }; const lo = new LimitedObject(); try { - lo.set("immutable", "mutable"); + lo.set('immutable', 'mutable'); } catch (e) { done(); } }); - it("fires errors when readonly attributes are unset", (done) => { - const LimitedObject = Parse.Object.extend("LimitedObject"); + it('fires errors when readonly attributes are unset', done => { + const LimitedObject = Parse.Object.extend('LimitedObject'); LimitedObject.readOnlyAttributes = function () { - return ["immutable"]; + return ['immutable']; }; const lo = new LimitedObject(); try { - lo.unset("immutable"); + lo.unset('immutable'); } catch (e) { done(); } }); - 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(); await testObject.save(); - let relation = o.relation("aRelation"); + let relation = o.relation('aRelation'); relation.add(testObject); await o.save(); const o2 = o.clone(); - assert.equal( - o.relation("aRelation").targetClassName, - o2.relation("aRelation").targetClassName - ); - let relations = await o.relation("aRelation").query().find(); + assert.equal(o.relation('aRelation').targetClassName, o2.relation('aRelation').targetClassName); + let relations = await o.relation('aRelation').query().find(); assert.equal(relations.length, 1); - relations = await o2.relation("aRelation").query().find(); + relations = await o2.relation('aRelation').query().find(); assert.equal(relations.length, 0); - relation = o2.relation("aRelation"); + relation = o2.relation('aRelation'); relation.add(testObject); await o2.save(); - relations = await o.relation("aRelation").query().find(); + relations = await o.relation('aRelation').query().find(); assert.equal(relations.length, 1); - relations = await o2.relation("aRelation").query().find(); + relations = await o2.relation('aRelation').query().find(); assert.equal(relations.length, 1); done(); }); - it("isDataAvailable", async () => { - const child = new TestObject({ foo: "bar" }); + it('isDataAvailable', async () => { + const child = new TestObject({ foo: 'bar' }); assert.equal(child.isDataAvailable(), false); const parent = new TestObject({ child }); @@ -2027,20 +2006,20 @@ describe("Parse Object", () => { const query = new Parse.Query(TestObject); const fetched = await query.get(parent.id); - const unfetched = fetched.get("child"); + const unfetched = fetched.get('child'); assert.equal(fetched.isDataAvailable(), true); assert.equal(unfetched.isDataAvailable(), false); }); - it("isDataAvailable user", async () => { + it('isDataAvailable user', async () => { let user = new Parse.User(); - user.set("username", "plain"); - user.set("password", "plain"); + user.set('username', 'plain'); + user.set('password', 'plain'); await user.signUp(); assert.equal(user.isDataAvailable(), true); - user = await Parse.User.logIn("plain", "plain"); + user = await Parse.User.logIn('plain', 'plain'); assert.equal(user.isDataAvailable(), true); const query = new Parse.Query(Parse.User); diff --git a/integration/test/ParsePolygonTest.js b/integration/test/ParsePolygonTest.js index 564ab5712..6c95c34b1 100644 --- a/integration/test/ParsePolygonTest.js +++ b/integration/test/ParsePolygonTest.js @@ -1,23 +1,23 @@ -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Polygon", () => { +describe('Polygon', () => { beforeAll(() => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); }); - beforeEach((done) => { + beforeEach(done => { clear().then(() => { done(); }); }); - it("can save polygon with points", (done) => { + it('can save polygon with points', done => { const openPoints = [ [0, 0], [0, 1], @@ -37,25 +37,25 @@ describe("Polygon", () => { .save() .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("polygon", polygon); + query.equalTo('polygon', polygon); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.deepEqual(results[0].get("polygon").coordinates, closedPoints); + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); const closedPolygon = new Parse.Polygon(closedPoints); const query = new Parse.Query(TestObject); - query.equalTo("polygon", closedPolygon); + query.equalTo('polygon', closedPolygon); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.deepEqual(results[0].get("polygon").coordinates, closedPoints); + 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); @@ -74,24 +74,24 @@ describe("Polygon", () => { .save() .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("polygon", polygon); + query.equalTo('polygon', polygon); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.deepEqual(results[0].get("polygon").coordinates, closedPoints); + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); const closedPolygon = new Parse.Polygon(closedPoints); const query = new Parse.Query(TestObject); - query.equalTo("polygon", closedPolygon); + query.equalTo('polygon', closedPolygon); return query.find(); }) - .then((results) => { - assert.deepEqual(results[0].get("polygon").coordinates, closedPoints); + .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) { @@ -99,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) { @@ -107,15 +107,15 @@ describe("Polygon", () => { } }); - it("fail save with invalid array", (done) => { + it('fail save with invalid array', done => { try { - new Parse.Polygon([["str1"], ["str2"], ["str3"]]); + new Parse.Polygon([['str1'], ['str2'], ['str3']]); } catch (e) { done(); } }); - it("containsPoint", (done) => { + it('containsPoint', done => { const points = [ [0, 0], [0, 1], @@ -131,7 +131,7 @@ describe("Polygon", () => { done(); }); - it("equality", (done) => { + it('equality', done => { const points = [ [0, 0], [0, 1], @@ -159,7 +159,7 @@ describe("Polygon", () => { done(); }); - it("supports polygonContains", (done) => { + it('supports polygonContains', done => { const p1 = [ [0, 0], [0, 1], @@ -192,16 +192,16 @@ describe("Polygon", () => { .then(() => { const point = new Parse.GeoPoint(0.5, 0.5); const query = new Parse.Query(TestObject); - query.polygonContains("polygon", point); + query.polygonContains('polygon', point); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); done(); }, done.fail); }); - it("polygonContains invalid input", (done) => { + it('polygonContains invalid input', done => { const points = [ [0, 0], [0, 1], @@ -214,7 +214,7 @@ describe("Polygon", () => { .save() .then(() => { const query = new Parse.Query(TestObject); - query.polygonContains("polygon", 1234); + query.polygonContains('polygon', 1234); return query.find(); }) .then(() => { diff --git a/integration/test/ParseQueryAggregateTest.js b/integration/test/ParseQueryAggregateTest.js index 2b80b7679..8d763944e 100644 --- a/integration/test/ParseQueryAggregateTest.js +++ b/integration/test/ParseQueryAggregateTest.js @@ -1,22 +1,22 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Parse Aggregate Query", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Aggregate Query', () => { + 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" }); + 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(() => { @@ -32,27 +32,27 @@ describe("Parse Aggregate Query", () => { ); }); - it("aggregate pipeline object query", (done) => { + it('aggregate pipeline object query', done => { const pipeline = { - group: { objectId: "$name" }, + 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 { @@ -62,52 +62,45 @@ describe("Parse Aggregate Query", () => { } }); - it("aggregate allow multiple of same stage", async () => { + it('aggregate allow multiple of same stage', async () => { const pointer1 = new TestObject({ value: 1 }); const pointer2 = new TestObject({ value: 2 }); const pointer3 = new TestObject({ value: 3 }); - const obj1 = new TestObject({ pointer: pointer1, name: "Hello" }); - const obj2 = new TestObject({ pointer: pointer2, name: "Hello" }); - const obj3 = new TestObject({ pointer: pointer3, name: "World" }); + const obj1 = new TestObject({ pointer: pointer1, name: 'Hello' }); + const obj2 = new TestObject({ pointer: pointer2, name: 'Hello' }); + const obj3 = new TestObject({ pointer: pointer3, name: 'World' }); const pipeline = [ { - match: { name: "Hello" }, + match: { name: 'Hello' }, }, { // Transform className$objectId to objectId and store in new field tempPointer project: { - tempPointer: { $substr: ["$_p_pointer", 11, -1] }, // Remove TestObject$ + tempPointer: { $substr: ['$_p_pointer', 11, -1] }, // Remove TestObject$ }, }, { // Left Join, replace objectId stored in tempPointer with an actual object lookup: { - from: "TestObject", - localField: "tempPointer", - foreignField: "_id", - as: "tempPointer", + from: 'TestObject', + localField: 'tempPointer', + foreignField: '_id', + as: 'tempPointer', }, }, { // lookup returns an array, Deconstructs an array field to objects unwind: { - path: "$tempPointer", + path: '$tempPointer', }, }, { - match: { "tempPointer.value": 2 }, + match: { 'tempPointer.value': 2 }, }, ]; - await Parse.Object.saveAll([ - pointer1, - pointer2, - pointer3, - obj1, - obj2, - obj3, - ]); + await Parse.Object.saveAll([pointer1, pointer2, pointer3, obj1, obj2, obj3]); const query = new Parse.Query(TestObject); const results = await query.aggregate(pipeline); @@ -116,28 +109,24 @@ describe("Parse Aggregate Query", () => { expect(results[0].tempPointer.value).toEqual(2); }); - it("aggregate pipeline on top of a simple query", async (done) => { + it('aggregate pipeline on top of a simple query', async done => { const pipeline = { - group: { objectId: "$name" }, + 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); done(); }); - it("distinct 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); @@ -146,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 b9d54c8b0..e71f41ddb 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -1,22 +1,22 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Parse Query", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Query', () => { + 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", + className: 'BoxedNumber', number: i, }); } @@ -35,40 +35,40 @@ describe("Parse Query", () => { ); }); - it("can do basic queries", (done) => { - const baz = new TestObject({ foo: "baz" }); - const qux = new TestObject({ foo: "qux" }); + 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"); + query.equalTo('foo', 'baz'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("foo"), "baz"); + assert.equal(results[0].get('foo'), 'baz'); done(); }); }); - it("can do a query with a limit", (done) => { - const baz = new TestObject({ foo: "baz" }); - const qux = new TestObject({ foo: "qux" }); + 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) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(["baz", "qux"].includes(results[0].get("foo")), true); + assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); done(); }) .catch(done.fail); }); - it("can do query with count", async () => { + it('can do query with count', async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: true })); @@ -79,15 +79,15 @@ describe("Parse Query", () => { query.withCount(true); const { results, count } = await query.find(); - assert(typeof count === "number"); + 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'); } }); - it("can do query withCount set to false", async () => { + it('can do query withCount set to false', async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: true })); @@ -100,21 +100,21 @@ 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 () => { + 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(); - assert(typeof count == "number"); + assert(typeof count == 'number'); assert.equal(results.length, 0); assert.equal(count, 0); }); - it("can do query with count and limit", async () => { + it('can do query with count and limit', async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: 2 })); @@ -126,12 +126,12 @@ describe("Parse Query", () => { const { results, count } = await query.find(); - assert(typeof count == "number"); + assert(typeof count == 'number'); assert.equal(results.length, 2); assert.equal(count, 4); }); - it("can do query withCount and skip", async () => { + it('can do query withCount and skip', async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: 2 })); @@ -143,12 +143,12 @@ describe("Parse Query", () => { const { results, count } = await query.find(); - assert(typeof count == "number"); + assert(typeof count == 'number'); assert.equal(results.length, 1); assert.equal(count, 4); }); - it("can do query when withCount set without arguments", async () => { + 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 })); @@ -159,12 +159,12 @@ describe("Parse Query", () => { const { results, count } = await query.find(); - assert(typeof count == "number"); + assert(typeof count == 'number'); assert.equal(results.length, 4); assert.equal(count, 4); }); - it("can do query when withCount undefined", async () => { + it('can do query when withCount undefined', async () => { const items = []; for (let i = 0; i < 4; i++) { items.push(new TestObject({ countMe: 2 })); @@ -176,17 +176,17 @@ describe("Parse Query", () => { const { results, count } = await query.find(); - assert(typeof count == "number"); + 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"); + const message = new Parse.Object('Message'); if (i > 0) { - message.set("prior", messageList[i - 1]); + message.set('prior', messageList[i - 1]); } messageList.push(message); } @@ -199,60 +199,60 @@ describe("Parse Query", () => { inList.push(messageList[0]); inList.push(messageList[2]); - const query = new Parse.Query("Message"); - query.containedIn("prior", inList); + const query = new Parse.Query('Message'); + query.containedIn('prior', inList); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); done(); }); }); - it("can do containsAll queries with numbers", (done) => { - const NumberSet = Parse.Object.extend("NumberSet"); + 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]); + query.containsAll('numbers', [1, 2, 3]); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); done(); }); }); - it("can do containsAll queries with strings", (done) => { - const StringSet = Parse.Object.extend("StringSet"); + 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"] })); + 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"]); + query.containsAll('strings', ['a', 'b', 'c']); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); done(); }); }); - it("can do containsAll queries with dates", (done) => { - const DateSet = Parse.Object.extend("DateSet"); + 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) { @@ -271,41 +271,38 @@ describe("Parse Query", () => { } function makeDates(stringArray) { - return stringArray.map((date) => { - return parseDate(date + "T00:00:00Z"); + 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"]), + 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"]), + 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"]) - ); + query.containsAll('dates', makeDates(['2013-02-01', '2013-02-02', '2013-02-03'])); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); done(); }) - .catch((e) => console.log(e)); + .catch(e => console.log(e)); }); - it("can do containsAll queries with objects", (done) => { - const MessageSet = Parse.Object.extend("MessageSet"); + it('can do containsAll queries with objects', done => { + const MessageSet = Parse.Object.extend('MessageSet'); const messageList = []; for (let i = 0; i < 4; i++) { @@ -333,17 +330,17 @@ describe("Parse Query", () => { inList.push(messageList[2]); const query = new Parse.Query(MessageSet); - query.containsAll("messages", inList); + query.containsAll('messages', inList); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); done(); }); }); - it("can do containedBy queries with numbers", async () => { - const NumberSet = Parse.Object.extend("NumberSet"); + it('can do containedBy queries with numbers', async () => { + const NumberSet = Parse.Object.extend('NumberSet'); const objectsList = []; objectsList.push(new NumberSet({ numbers: [0, 1, 2] })); objectsList.push(new NumberSet({ numbers: [2, 0] })); @@ -352,218 +349,218 @@ describe("Parse Query", () => { await Parse.Object.saveAll(objectsList); const query = new Parse.Query(NumberSet); - query.containedBy("numbers", [1, 2, 3, 4, 5]); + query.containedBy('numbers', [1, 2, 3, 4, 5]); const results = await query.find(); assert.equal(results.length, 1); }); - it("can do containedBy queries with pointer", async () => { - const objects = Array.from(Array(10).keys()).map((idx) => { - const obj = new Parse.Object("Object"); - obj.set("key", idx); + it('can do containedBy queries with pointer', async () => { + const objects = Array.from(Array(10).keys()).map(idx => { + const obj = new Parse.Object('Object'); + obj.set('key', idx); return obj; }); - const parent1 = new Parse.Object("Parent"); - const parent2 = new Parse.Object("Parent"); - const parent3 = new Parse.Object("Parent"); + const parent1 = new Parse.Object('Parent'); + const parent2 = new Parse.Object('Parent'); + const parent3 = new Parse.Object('Parent'); await Parse.Object.saveAll(objects); // [0, 1, 2] - parent1.set("objects", objects.slice(0, 3)); + parent1.set('objects', objects.slice(0, 3)); const shift = objects.shift(); // [2, 0] - parent2.set("objects", [objects[1], shift]); + parent2.set('objects', [objects[1], shift]); // [1, 2, 3, 4] - parent3.set("objects", objects.slice(1, 4)); + parent3.set('objects', objects.slice(1, 4)); await Parse.Object.saveAll([parent1, parent2, parent3]); - const query = new Parse.Query("Parent"); - query.containedBy("objects", objects); + const query = new Parse.Query('Parent'); + query.containedBy('objects', objects); const results = await query.find(); assert.equal(results.length, 1); assert.equal(results[0].id, parent3.id); }); - it("can do equalTo queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", 3); - query.find().then((results) => { + it('can do equalTo queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 3); + query.find().then(results => { assert.equal(results.length, 1); done(); }); }); - it("can do equalTo queries with object", (done) => { - const query = new Parse.Query("BoxedNumber"); + 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) => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", undefined); - query.find().then((results) => { + it('can test equality with undefined', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', undefined); + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it("can perform lessThan queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.lessThan("number", 7); - query.find().then((results) => { + it('can perform lessThan queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.lessThan('number', 7); + query.find().then(results => { assert.equal(results.length, 7); done(); }); }); - it("can perform lessThanOrEqualTo queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.lessThanOrEqualTo("number", 7); - query.find().then((results) => { + it('can perform lessThanOrEqualTo queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.lessThanOrEqualTo('number', 7); + query.find().then(results => { assert.equal(results.length, 8); done(); }); }); - it("can perform greaterThan queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThan("number", 7); - query.find().then((results) => { + it('can perform greaterThan queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.greaterThan('number', 7); + query.find().then(results => { assert.equal(results.length, 2); done(); }); }); - it("can perform greaterThanOrEqualTo queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThanOrEqualTo("number", 7); - query.find().then((results) => { + it('can perform greaterThanOrEqualTo queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.greaterThanOrEqualTo('number', 7); + query.find().then(results => { assert.equal(results.length, 3); 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) => { + 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 => { assert.equal(results.length, 1); 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) => { + 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 => { assert.equal(results.length, 5); done(); }); }); - it("can perform notEqualTo queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.notEqualTo("number", 5); - query.find().then((results) => { + it('can perform notEqualTo queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.notEqualTo('number', 5); + query.find().then(results => { assert.equal(results.length, 9); done(); }); }); - it("can perform notEqualTo queries with object", (done) => { - const query = new Parse.Query("BoxedNumber"); + 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) => { - const query = new Parse.Query("BoxedNumber"); - query.containedIn("number", [3, 5, 7, 9, 11]); - query.find().then((results) => { + it('can perform containedIn queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.containedIn('number', [3, 5, 7, 9, 11]); + query.find().then(results => { assert.equal(results.length, 4); 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) => { + it('can perform notContainedIn queries', done => { + const query = new Parse.Query('BoxedNumber'); + 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") + 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"); + .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) => { + .then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("number"), 2); - assert.equal(results[1].get("number"), 3); + 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") + it('can test objectId in equalTo queries', done => { + new Parse.Query('BoxedNumber') + .ascending('number') .find() - .then((numbers) => { + .then(numbers => { const id = numbers[5].id; - const query = new Parse.Query("BoxedNumber"); - query.equalTo("objectId", id); - query.ascending("number"); + const query = new Parse.Query('BoxedNumber'); + query.equalTo('objectId', id); + query.ascending('number'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("number"), 5); + assert.equal(results[0].get('number'), 5); done(); }); }); - it("can find no elements", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("number", 15); - query.find().then((results) => { + it('can find no elements', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 15); + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it("handles when find throws errors", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("$foo", "bar"); - query.find().catch((e) => { + it('handles when find throws errors', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('$foo', 'bar'); + 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() @@ -571,7 +568,7 @@ describe("Parse Query", () => { const query = new Parse.Query(TestObject); return query.get(object.id); }) - .then((result) => { + .then(result => { assert.equal(result.id, object.id); assert(result.createdAt); assert(result.updatedAt); @@ -579,7 +576,7 @@ describe("Parse Query", () => { }); }); - it("handles get with undefined id", (done) => { + it('handles get with undefined id', done => { const object = new TestObject(); object .save() @@ -587,13 +584,13 @@ describe("Parse Query", () => { const query = new Parse.Query(TestObject); return query.get(undefined); }) - .catch((e) => { + .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() @@ -601,76 +598,76 @@ describe("Parse Query", () => { const query = new Parse.Query(TestObject); return query.get(undefined); }) - .catch((e) => { + .catch(e => { assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); done(); }); }); - it("can query for the first result", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.ascending("number"); - query.first().then((result) => { - assert.equal(result.get("number"), 0); + it('can query for the first result', done => { + const query = new Parse.Query('BoxedNumber'); + query.ascending('number'); + query.first().then(result => { + assert.equal(result.get('number'), 0); 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) => { + it('can query for the first with no results', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('number', 20); + query.first().then(result => { assert.equal(result, undefined); done(); }); }); - it("can query for the first with two results", (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); + query.equalTo('x', 44); return query.first(); }) - .then((result) => { - assert.equal(result.get("x"), 44); + .then(result => { + assert.equal(result.get('x'), 44); done(); }); }); - it("handles when first throws errors", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.equalTo("$foo", "bar"); - query.first().catch((e) => { + it('handles when first throws errors', done => { + const query = new Parse.Query('BoxedNumber'); + query.equalTo('$foo', 'bar'); + 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", + className: 'CoolContainer', item: item1, }); const container2 = new Parse.Object({ - className: "CoolContainer", + className: 'CoolContainer', item: item2, }); Parse.Object.saveAll([item1, item2, container1, container2]) .then(() => { - const query = new Parse.Query("CoolContainer"); - query.notEqualTo("item", item1); + const query = new Parse.Query('CoolContainer'); + query.notEqualTo('item', item1); return query.find(); }) - .then((results) => { + .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 }), @@ -678,24 +675,24 @@ describe("Parse Query", () => { ]) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("canSkip", true); + query.equalTo('canSkip', true); query.skip(1); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); const query = new Parse.Query(TestObject); - query.equalTo("canSkip", true); + query.equalTo('canSkip', true); query.skip(3); return query.find(); }) - .then((results) => { + .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 }), @@ -703,225 +700,225 @@ describe("Parse Query", () => { ]) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); return query.count(); }) - .then((count) => { + .then(count => { assert.equal(count, 3); const query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); query.skip(1); return query.count(); }) - .then((count) => { + .then(count => { assert.equal(count, 3); const query = new Parse.Query(TestObject); - query.equalTo("skipCount", true); + query.equalTo('skipCount', true); query.skip(2); return query.count(); }) - .then((count) => { + .then(count => { assert.equal(count, 3); done(); }); }); - it("can perform count queries", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.greaterThan("number", 1); - query.count().then((count) => { + it('can perform count queries', done => { + const query = new Parse.Query('BoxedNumber'); + query.greaterThan('number', 1); + query.count().then(count => { assert.equal(count, 8); done(); }); }); - it("can order by ascending numbers", (done) => { - const query = new Parse.Query("BoxedNumber"); - query.ascending("number"); - query.find().then((results) => { - assert.equal(results[0].get("number"), 0); - assert.equal(results[9].get("number"), 9); + it('can order by ascending numbers', done => { + const query = new Parse.Query('BoxedNumber'); + query.ascending('number'); + 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) => { - const query = new Parse.Query("BoxedNumber"); - query.descending("number"); - query.find().then((results) => { - assert.equal(results[0].get("number"), 9); - assert.equal(results[9].get("number"), 0); + it('can order by descending numbers', done => { + const query = new Parse.Query('BoxedNumber'); + query.descending('number'); + 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" }), + 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"); + query.equalTo('doubleOrder', true); + query.ascending('number').addDescending('string'); return query.find(); }) - .then((results) => { + .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"); + 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" }), + 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"); + query.equalTo('otherDoubleOrder', true); + query.descending('number').addAscending('string'); return query.find(); }) - .then((results) => { + .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"); + 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" }), + 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"); + query.equalTo('doubleDescending', true); + query.descending('number,string'); return query.find(); }) - .then((results) => { + .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"); + 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"); + query.equalTo('doubleDescending', true); + query.descending('number, string'); return query.find(); }) - .then((results) => { + .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"); + 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"]); + query.equalTo('doubleDescending', true); + query.descending(['number', 'string']); return query.find(); }) - .then((results) => { + .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"); + 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"); + query.equalTo('doubleDescending', true); + query.descending('number', 'string'); return query.find(); }) - .then((results) => { + .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"); + 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) => { - const query = new Parse.Query("BoxedNumber"); - query.ascending("_password"); - query.find().catch((e) => { + it('can not order by password', done => { + const query = new Parse.Query('BoxedNumber'); + query.ascending('_password'); + 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 }) + it('can order by _created_at', done => { + new Parse.Object({ className: 'TestObject', orderedDate: true }) .save() .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate: true, }).save(); }) .then(() => { - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate", true); - query.ascending("_created_at"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate', true); + query.ascending('_created_at'); return query.find(); }) - .then((results) => { + .then(results => { assert(results[0].createdAt < results[1].createdAt); assert(results[1].createdAt < results[2].createdAt); assert(results[2].createdAt < results[3].createdAt); @@ -929,34 +926,34 @@ describe("Parse Query", () => { }); }); - it("can order by createdAt", (done) => { - new Parse.Object({ className: "TestObject", orderedDate2: true }) + it('can order by createdAt', done => { + new Parse.Object({ className: 'TestObject', orderedDate2: true }) .save() .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate2: true, }).save(); }) .then(() => { - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate2", true); - query.descending("createdAt"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate2', true); + query.descending('createdAt'); return query.find(); }) - .then((results) => { + .then(results => { assert(results[0].createdAt > results[1].createdAt); assert(results[1].createdAt > results[2].createdAt); assert(results[2].createdAt > results[3].createdAt); @@ -964,34 +961,34 @@ describe("Parse Query", () => { }); }); - it("can order by _updated_at", (done) => { - new Parse.Object({ className: "TestObject", orderedDate3: true }) + it('can order by _updated_at', done => { + new Parse.Object({ className: 'TestObject', orderedDate3: true }) .save() .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate3: true, }).save(); }) .then(() => { - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate3", true); - query.ascending("_updated_at"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate3', true); + query.ascending('_updated_at'); return query.find(); }) - .then((results) => { + .then(results => { assert(results[0].updatedAt < results[1].updatedAt); assert(results[1].updatedAt < results[2].updatedAt); assert(results[2].updatedAt < results[3].updatedAt); @@ -999,34 +996,34 @@ describe("Parse Query", () => { }); }); - it("can order by updatedAt", (done) => { - new Parse.Object({ className: "TestObject", orderedDate4: true }) + it('can order by updatedAt', done => { + new Parse.Object({ className: 'TestObject', orderedDate4: true }) .save() .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', orderedDate4: true, }).save(); }) .then(() => { - const query = new Parse.Query("TestObject"); - query.equalTo("orderedDate4", true); - query.descending("updatedAt"); + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate4', true); + query.descending('updatedAt'); return query.find(); }) - .then((results) => { + .then(results => { assert(results[0].updatedAt > results[1].updatedAt); assert(results[1].updatedAt > results[2].updatedAt); assert(results[2].updatedAt > results[3].updatedAt); @@ -1034,64 +1031,64 @@ describe("Parse Query", () => { }); }); - it("can test time equality", (done) => { - new Parse.Object({ className: "TestObject", timed: true, name: "item1" }) + it('can test time equality', done => { + new Parse.Object({ className: 'TestObject', timed: true, name: 'item1' }) .save() .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item2", + name: 'item2', }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item3", + name: 'item3', }).save(); }) .then(() => { return new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed: true, - name: "item4", + name: 'item4', }).save(); }) - .then((last) => { - const query = new Parse.Query("TestObject"); - query.equalTo("timed", true); - query.equalTo("createdAt", last.createdAt); + .then(last => { + const query = new Parse.Query('TestObject'); + query.equalTo('timed', true); + query.equalTo('createdAt', last.createdAt); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "item4"); + 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", + className: 'TestObject', timed2: true, - name: "item1", + name: 'item1', }), new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item2", + name: 'item2', }), new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item3", + name: 'item3', }), new Parse.Object({ - className: "TestObject", + className: 'TestObject', timed2: true, - name: "item4", + name: 'item4', }), ]; @@ -1107,23 +1104,23 @@ describe("Parse Query", () => { return objects[3].save(); }) .then(() => { - const query = new Parse.Query("TestObject"); - query.equalTo("timed2", true); - query.lessThan("createdAt", objects[2].createdAt); - query.ascending("createdAt"); + const query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.lessThan('createdAt', objects[2].createdAt); + query.ascending('createdAt'); return query.find(); }) - .then((results) => { + .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); + const query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.greaterThan('createdAt', objects[2].createdAt); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); assert.equal(results[0].id, objects[3].id); done(); @@ -1131,367 +1128,367 @@ describe("Parse Query", () => { .catch(done.fail); }); - it("can test string matching", (done) => { + it('can test string matching', done => { const obj1 = new TestObject(); - obj1.set("myString", "football"); + obj1.set('myString', 'football'); const obj2 = new TestObject(); - obj2.set("myString", "soccer"); + obj2.set('myString', 'soccer'); Parse.Object.saveAll([obj1, obj2]) .then(() => { const query = new Parse.Query(TestObject); - query.matches("myString", "^fo*\\wb[^o]l+$"); + query.matches('myString', '^fo*\\wb[^o]l+$'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "football"); + assert.equal(results[0].get('myString'), 'football'); const query = new Parse.Query(TestObject); - query.matches("myString", /^fo*\wb[^o]l+$/); + query.matches('myString', /^fo*\wb[^o]l+$/); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "football"); + 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.set('myString', 'hockey'); obj .save() .then(() => { const query = new Parse.Query(TestObject); - query.matches("myString", "Hockey", "i"); + query.matches('myString', 'Hockey', 'i'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("myString"), "hockey"); + 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.matches('myString', 'football', 'some invalid thing'); + 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.set('website', 'PArSe\nCom'); obj .save() .then(() => { const query = new Parse.Query(TestObject); query.matches( - "website", + '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" + 'insensitively\n.com # Second fragment. This can be separated by any ' + + 'character, including newline\n', + 'mixs' ); return query.find(); }) - .then((results) => { + .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.set('website', '\n\nbuffer\n\nparse.COM'); obj .save() .then(() => { const query = new Parse.Query(TestObject); - query.matches("website", /parse\.com/im); + query.matches('website', /parse\.com/im); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); done(); }); }); - it("can test contains", (done) => { + 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: '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); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); const query = new Parse.Query(TestObject); - query.equalTo("contains", true); - query.startsWith("myString", someAscii); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); return query.find(); }) - .then((results) => { + .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(); if (i % 2) { - item.set("y", i + 1); + item.set('y', i + 1); } else { - item.set("z", i + 1); + item.set('z', i + 1); } objects.push(item); } Parse.Object.saveAll(objects) .then(() => { const query = new Parse.Query(TestObject); - query.exists("y"); + query.exists('y'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("y")); + assert(results[i].has('y')); } done(); }) - .catch((e) => console.log(e)); + .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 }); if (i % 2) { - item.set("y", i + 1); + item.set('y', i + 1); } else { - item.set("z", i + 1); + item.set('z', i + 1); } objects.push(item); } Parse.Object.saveAll(objects) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("dne", true); - query.doesNotExist("y"); + query.equalTo('dne', true); + query.doesNotExist('y'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("z")); + 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", { + const container = new Parse.Object('Container', { relation_exists: true, }); if (i % 2) { - container.set("y", i); + container.set('y', i); } else { const item = new TestObject(); - item.set("x", i); - container.set("x", item); + item.set('x', i); + container.set('x', item); objects.push(item); } objects.push(container); } Parse.Object.saveAll(objects) .then(() => { - const query = new Parse.Query("Container"); - query.equalTo("relation_exists", true); - query.exists("x"); + const query = new Parse.Query('Container'); + query.equalTo('relation_exists', true); + query.exists('x'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("x")); + 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 }); + const container = new Parse.Object('Container', { relation_dne: true }); if (i % 2) { - container.set("y", i); + container.set('y', i); } else { const item = new TestObject(); - item.set("x", i); - container.set("x", item); + item.set('x', i); + container.set('x', item); objects.push(item); } objects.push(container); } Parse.Object.saveAll(objects) .then(() => { - const query = new Parse.Query("Container"); - query.equalTo("relation_dne", true); - query.doesNotExist("x"); + const query = new Parse.Query('Container'); + query.equalTo('relation_dne', true); + query.doesNotExist('x'); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 5); for (let i = 0; i < results.length; i++) { - assert(results[i].has("y")); + 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); + 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); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); return query.find(); }) - .then((results) => { + .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")); + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert(!parentAgain.get('child').get('foo')); done(); }) - .catch((e) => console.log(e)); + .catch(e => console.log(e)); }); - it("can include nested objects", (done) => { + it('can include nested objects', done => { const child = new TestObject(); - const parent = new Parse.Object("Container"); - child.set("foo", "bar"); - parent.set("child", child); + 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"); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include('child'); return query.find(); }) - .then((results) => { + .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"); + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert.equal(parentAgain.get('child').get('foo'), 'bar'); done(); }); }); - it("can includeAll nested objects", async () => { - const child1 = new TestObject({ foo: "bar" }); - const child2 = new TestObject({ foo: "baz" }); - const child3 = new TestObject({ foo: "bin" }); - const parent = new Parse.Object("Container"); - parent.set("child1", child1); - parent.set("child2", child2); - parent.set("child3", child3); + it('can includeAll nested objects', async () => { + const child1 = new TestObject({ foo: 'bar' }); + const child2 = new TestObject({ foo: 'baz' }); + const child3 = new TestObject({ foo: 'bin' }); + const parent = new Parse.Object('Container'); + parent.set('child1', child1); + parent.set('child2', child2); + parent.set('child3', child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); query.includeAll(); const results = await query.find(); assert.equal(results.length, 1); const parentAgain = results[0]; - assert.equal(parentAgain.get("child1").get("foo"), "bar"); - assert.equal(parentAgain.get("child2").get("foo"), "baz"); - assert.equal(parentAgain.get("child3").get("foo"), "bin"); - }); - - it("can includeAll nested objects in .each", async () => { - const child1 = new TestObject({ foo: "bar" }); - const child2 = new TestObject({ foo: "baz" }); - const child3 = new TestObject({ foo: "bin" }); - const parent = new Parse.Object("Container"); - parent.set("child1", child1); - parent.set("child2", child2); - parent.set("child3", child3); + assert.equal(parentAgain.get('child1').get('foo'), 'bar'); + assert.equal(parentAgain.get('child2').get('foo'), 'baz'); + assert.equal(parentAgain.get('child3').get('foo'), 'bin'); + }); + + it('can includeAll nested objects in .each', async () => { + const child1 = new TestObject({ foo: 'bar' }); + const child2 = new TestObject({ foo: 'baz' }); + const child3 = new TestObject({ foo: 'bin' }); + const parent = new Parse.Object('Container'); + parent.set('child1', child1); + parent.set('child2', child2); + parent.set('child3', child3); await Parse.Object.saveAll([child1, child2, child3, parent]); - const query = new Parse.Query("Container"); - query.equalTo("objectId", parent.id); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); query.includeAll(); - 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"); + 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'); }); }); - it("can return all objects with findAll", async () => { - const objs = [...Array(101)].map(() => new Parse.Object("Container")); + it('can return all objects with findAll', async () => { + const objs = [...Array(101)].map(() => new Parse.Object('Container')); await Parse.Object.saveAll(objs); - const query = new Parse.Query("Container"); + const query = new Parse.Query('Container'); const result = await query.findAll(); 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); + 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"]); + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include(['child']); return query.find(); }) - .then((results) => { + .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"); + 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) => { - const Child = Parse.Object.extend("Child"); - const Parent = Parse.Object.extend("Parent"); - const Grandparent = Parse.Object.extend("Grandparent"); + 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'); const objects = []; for (let i = 0; i < 5; i++) { @@ -1511,116 +1508,116 @@ describe("Parse Query", () => { Parse.Object.saveAll(objects) .then(() => { - const q = new Parse.Query("Grandparent"); - q.equalTo("nested", true); - q.include("parent.child"); + const q = new Parse.Query('Grandparent'); + q.equalTo('nested', true); + q.include('parent.child'); return q.find(); }) - .then((results) => { + .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")); + 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(); }); }); - 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"); + 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); + const query = new Parse.Query('ParentObject'); + query.include('child'); + query.equalTo('objectId', parent.id); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); const parentAgain = results[0]; - const childAgain = parentAgain.get("child"); + const childAgain = parentAgain.get('child'); assert.equal(child.id, childAgain.id); assert.equal(parent.id, parentAgain.id); - assert.equal(childAgain.get("foo"), "bar"); + assert.equal(childAgain.get('foo'), 'bar'); assert(!parentAgain.dirty()); assert(!childAgain.dirty()); done(); }); }); - it("can exclude keys", async () => { + it('can exclude keys', async () => { const object = new TestObject({ - hello: "world", - foo: "bar", - slice: "pizza", + hello: 'world', + foo: 'bar', + slice: 'pizza', }); await object.save(); const query = new Parse.Query(TestObject); - query.exclude("foo"); + query.exclude('foo'); const result = await query.get(object.id); - assert.equal(result.get("foo"), undefined); - assert.equal(result.get("hello"), "world"); - assert.equal(result.get("slice"), "pizza"); + assert.equal(result.get('foo'), undefined); + assert.equal(result.get('hello'), 'world'); + assert.equal(result.get('slice'), 'pizza'); }); - it("can exclude multiple keys", async () => { + it('can exclude multiple keys', async () => { const object = new TestObject({ - hello: "world", - foo: "bar", - slice: "pizza", + hello: 'world', + foo: 'bar', + slice: 'pizza', }); await object.save(); const query = new Parse.Query(TestObject); - query.exclude(["foo", "hello"]); + query.exclude(['foo', 'hello']); const result = await query.get(object.id); - assert.equal(result.get("foo"), undefined); - assert.equal(result.get("hello"), undefined); - assert.equal(result.get("slice"), "pizza"); + assert.equal(result.get('foo'), undefined); + assert.equal(result.get('hello'), undefined); + assert.equal(result.get('slice'), 'pizza'); }); - it("uses subclasses when creating objects", (done) => { - const ParentObject = Parse.Object.extend({ className: "ParentObject" }); - let ChildObject = Parse.Object.extend("ChildObject", { + it('uses subclasses when creating objects', done => { + const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); + let ChildObject = Parse.Object.extend('ChildObject', { foo() { - return "foo"; + return 'foo'; }, }); const parent = new ParentObject(); const child = new ChildObject(); - parent.set("child", child); + parent.set('child', child); Parse.Object.saveAll([child, parent]) .then(() => { - ChildObject = Parse.Object.extend("ChildObject", { + ChildObject = Parse.Object.extend('ChildObject', { bar() { - return "bar"; + return 'bar'; }, }); const query = new Parse.Query(ParentObject); - query.equalTo("objectId", parent.id); - query.include("child"); + query.equalTo('objectId', parent.id); + query.include('child'); return query.find(); }) - .then((results) => { + .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"); + 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) => { - const ParentObject = Parse.Object.extend("ParentObject"); - const ChildObject = Parse.Object.extend("ChildObject"); + 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( @@ -1633,24 +1630,24 @@ describe("Parse Query", () => { Parse.Object.saveAll(objects) .then(() => { const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo("qtest", true); - subQuery.greaterThan("x", 5); + subQuery.equalTo('qtest', true); + subQuery.greaterThan('x', 5); const q = new Parse.Query(ParentObject); - q.matchesQuery("child", subQuery); + q.matchesQuery('child', subQuery); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 4); - results.forEach((o) => { - assert(o.get("x") > 15); + results.forEach(o => { + assert(o.get('x') > 15); }); done(); }); }); - it("can not match the results of another query", (done) => { - const ParentObject = Parse.Object.extend("ParentObject"); - const ChildObject = Parse.Object.extend("ChildObject"); + 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( @@ -1664,271 +1661,271 @@ describe("Parse Query", () => { Parse.Object.saveAll(objects) .then(() => { const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo("dneqtest", true); - subQuery.greaterThan("x", 5); + subQuery.equalTo('dneqtest', true); + subQuery.greaterThan('x', 5); const q = new Parse.Query(ParentObject); - q.equalTo("dneqtest", true); - q.doesNotMatchQuery("child", subQuery); + q.equalTo('dneqtest', true); + q.doesNotMatchQuery('child', subQuery); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 6); - results.forEach((o) => { - assert(o.get("x") >= 10); - assert(o.get("x") <= 15); + results.forEach(o => { + assert(o.get('x') >= 10); + assert(o.get('x') <= 15); }); done(); }) - .catch((err) => { + .catch(err => { console.dir(err); done.fail(); }); }); - it("can select keys from a matched query", (done) => { - const Restaurant = Parse.Object.extend("Restaurant"); - const Person = Parse.Object.extend("Person"); + it('can select keys from a matched query', done => { + const Restaurant = Parse.Object.extend('Restaurant'); + const Person = Parse.Object.extend('Person'); const objects = [ - new Restaurant({ rating: 5, location: "Djibouti" }), - new Restaurant({ rating: 3, location: "Ouagadougou" }), - new Person({ name: "Bob", hometown: "Djibouti" }), - new Person({ name: "Tom", hometown: "Ouagadougou" }), - new Person({ name: "Billy", hometown: "Detroit" }), + new Restaurant({ rating: 5, location: 'Djibouti' }), + new Restaurant({ rating: 3, location: 'Ouagadougou' }), + new Person({ name: 'Bob', hometown: 'Djibouti' }), + new Person({ name: 'Tom', hometown: 'Ouagadougou' }), + new Person({ name: 'Billy', hometown: 'Detroit' }), ]; Parse.Object.saveAll(objects) .then(() => { const query = new Parse.Query(Restaurant); - query.greaterThan("rating", 4); + query.greaterThan('rating', 4); const mainQuery = new Parse.Query(Person); - mainQuery.matchesKeyInQuery("hometown", "location", query); + mainQuery.matchesKeyInQuery('hometown', 'location', query); return mainQuery.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("name"), "Bob"); + assert.equal(results[0].get('name'), 'Bob'); const query = new Parse.Query(Restaurant); - query.greaterThan("rating", 4); + query.greaterThan('rating', 4); const mainQuery = new Parse.Query(Person); - mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); - mainQuery.ascending("name"); + mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); + mainQuery.ascending('name'); return mainQuery.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); - assert.equal(results[0].get("name"), "Billy"); - assert.equal(results[1].get("name"), "Tom"); + 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.set('length', 5); + assert.equal(obj.get('length'), 5); obj .save() .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("objectId", obj.id); + query.equalTo('objectId', obj.id); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("length"), 5); + assert.equal(results[0].get('length'), 5); done(); }); }); - it("can include User fields", (done) => { - Parse.User.signUp("bob", "password", { age: 21 }) - .then((user) => { + 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) => { + .then(obj => { const query = new Parse.Query(TestObject); - query.include("owner"); + 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); + .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"); + 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 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) => { + .then(results => { assert.equal(results.length, 6); - results.forEach((number) => { - assert(number.get("x") < 2 || number.get("x") > 5); + results.forEach(number => { + assert(number.get('x') < 2 || number.get('x') > 5); }); 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"); - child.set("x", i); - child.set("complexor", true); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("complexor", true); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + child.set('complexor', true); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('complexor', true); + 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 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) => { + .then(results => { assert.equal(results.length, 3); done(); }) .catch(done.fail); }); - it("can build AND queries", (done) => { + it('can build AND queries', done => { const objects = []; for (let i = 0; i < 10; i++) { - const obj = new Parse.Object("BoxedNumber"); + 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 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) => { + .then(results => { assert.equal(results.length, 2); - results.forEach((number) => { - assert(number.get("x") > 2 && number.get("x") < 5); + results.forEach(number => { + assert(number.get('x') > 2 && number.get('x') < 5); }); done(); }) - .catch((e) => console.log(e)); + .catch(e => console.log(e)); }); - it("can build complex AND queries", (done) => { + it('can build complex AND queries', done => { const objects = []; for (let i = 0; i < 10; i++) { - const child = new Parse.Object("Child"); - child.set("x", i); - child.set("and", true); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("and", true); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + child.set('and', true); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('and', true); + 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 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) => { + .then(results => { assert.equal(results.length, 1); done(); }) .catch(done.fail); }); - it("can build NOR queries", async () => { + it('can build NOR queries', async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const obj = new Parse.Object("NORTest"); + const obj = new Parse.Object('NORTest'); obj.set({ x: i }); objects.push(obj); } await Parse.Object.saveAll(objects); - const q1 = new Parse.Query("NORTest"); - q1.greaterThan("x", 5); - const q2 = new Parse.Query("NORTest"); - q2.lessThan("x", 3); + const q1 = new Parse.Query('NORTest'); + q1.greaterThan('x', 5); + const q2 = new Parse.Query('NORTest'); + q2.lessThan('x', 3); const norQuery = Parse.Query.nor(q1, q2); const results = await norQuery.find(); assert.equal(results.length, 3); - results.forEach((number) => { - assert(number.get("x") >= 3 && number.get("x") <= 5); + results.forEach(number => { + assert(number.get('x') >= 3 && number.get('x') <= 5); }); }); - it("can build complex NOR queries", async () => { + it('can build complex NOR queries', async () => { const objects = []; for (let i = 0; i < 10; i += 1) { - const child = new Parse.Object("Child"); - child.set("x", i); - const parent = new Parse.Object("Parent"); - parent.set("child", child); - parent.set("y", i); + const child = new Parse.Object('Child'); + child.set('x', i); + const parent = new Parse.Object('Parent'); + parent.set('child', child); + parent.set('y', i); objects.push(parent); } await Parse.Object.saveAll(objects); - const subQuery = new Parse.Query("Child"); - subQuery.equalTo("x", 4); - const q1 = new Parse.Query("Parent"); - q1.matchesQuery("child", subQuery); - const q2 = new Parse.Query("Parent"); - q2.equalTo("y", 5); + const subQuery = new Parse.Query('Child'); + subQuery.equalTo('x', 4); + const q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); + const q2 = new Parse.Query('Parent'); + q2.equalTo('y', 5); const norQuery = Parse.Query.nor(q1, q2); const results = await norQuery.find(); assert.equal(results.length, 8); - results.forEach((number) => { - assert(number.get("x") !== 4 || number.get("x") !== 5); + 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 })); @@ -1937,11 +1934,11 @@ describe("Parse Query", () => { Parse.Object.saveAll(items) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + query.equalTo('eachtest', true); + query.lessThan('x', 25); - return query.each((obj) => { - seen[obj.get("x")] = (seen[obj.get("x")] || 0) + 1; + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); }) .then(() => { @@ -1953,7 +1950,7 @@ describe("Parse Query", () => { }); }); - 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 })); @@ -1962,12 +1959,12 @@ describe("Parse Query", () => { Parse.Object.saveAll(items) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); - query.ascending("x"); + 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; + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); }) .then(null, () => { @@ -1975,7 +1972,7 @@ describe("Parse Query", () => { }); }); - 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 })); @@ -1984,12 +1981,12 @@ describe("Parse Query", () => { Parse.Object.saveAll(items) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + 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; + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); }) .then(null, () => { @@ -1997,7 +1994,7 @@ describe("Parse Query", () => { }); }); - 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 })); @@ -2006,12 +2003,12 @@ describe("Parse Query", () => { Parse.Object.saveAll(items) .then(() => { const query = new Parse.Query(TestObject); - query.equalTo("eachtest", true); - query.lessThan("x", 25); + 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; + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); }) .then(null, () => { @@ -2019,39 +2016,39 @@ describe("Parse Query", () => { }); }); - it("can select specific keys", (done) => { - const obj = new TestObject({ foo: "baz", bar: 1 }); + 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"); + q.equalTo('objectId', obj.id); + q.select('foo'); return q.first(); }) - .then((result) => { + .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); + assert.equal(result.get('foo'), 'baz'); + assert.equal(result.get('bar'), undefined); done(); }); }); - it("can select specific keys with each", (done) => { - const obj = new TestObject({ foo: "baz", bar: 1 }); + 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) => { + 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); + assert.equal(o.get('foo'), 'baz'); + assert.equal(o.get('bar'), undefined); }); }) .then(() => { @@ -2059,16 +2056,16 @@ describe("Parse Query", () => { }); }); - it("can perform a full text search", () => { + it('can perform a full text search', () => { const subjects = [ - "coffee", - "Coffee Shopping", - "Baking a cake", - "baking", - "Café Con Leche", - "Сырники", - "coffee and cream", - "Cafe con Leche", + 'coffee', + 'Coffee Shopping', + 'Baking a cake', + 'baking', + 'Café Con Leche', + 'Сырники', + 'coffee and cream', + 'Cafe con Leche', ]; const objects = []; for (const i in subjects) { @@ -2078,24 +2075,24 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestObject); - q.fullText("subject", "coffee"); + q.fullText('subject', 'coffee'); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 3); }); }); - it("can perform a full text search sort", () => { + it('can perform a full text search sort', () => { const subjects = [ - "coffee", - "Coffee Shopping", - "Baking a cake", - "baking", - "Café Con Leche", - "Сырники", - "coffee and cream", - "Cafe con Leche", + 'coffee', + 'Coffee Shopping', + 'Baking a cake', + 'baking', + 'Café Con Leche', + 'Сырники', + 'coffee and cream', + 'Cafe con Leche', ]; const objects = []; for (const i in subjects) { @@ -2105,31 +2102,31 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestObject); - q.fullText("subject", "coffee"); - q.ascending("$score"); - q.select("$score"); + q.fullText('subject', 'coffee'); + q.ascending('$score'); + q.select('$score'); return q.find(); }) - .then((results) => { + .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); + 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", () => { + it('can perform a full text search with language options', () => { const subjects = [ - "café", - "loja de café", - "preparando um café", - "preparar", - "café com leite", - "Сырники", - "prepare café e creme", - "preparação de cafe com leite", + 'café', + 'loja de café', + 'preparando um café', + 'preparar', + 'café com leite', + 'Сырники', + 'prepare café e creme', + 'preparação de cafe com leite', ]; - const TestLanguageOption = Parse.Object.extend("TestLanguageOption"); + const TestLanguageOption = Parse.Object.extend('TestLanguageOption'); const objects = []; for (const i in subjects) { const obj = new TestLanguageOption({ language_comment: subjects[i] }); @@ -2138,26 +2135,26 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestLanguageOption); - q.fullText("language_comment", "preparar", { language: "portuguese" }); + q.fullText('language_comment', 'preparar', { language: 'portuguese' }); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); }); }); - it("can perform a full text search with case sensitive options", () => { + it('can perform a full text search with case sensitive options', () => { const subjects = [ - "café", - "loja de café", - "Preparando um café", - "preparar", - "café com leite", - "Сырники", - "Preparar café e creme", - "preparação de cafe com leite", + 'café', + 'loja de café', + 'Preparando um café', + 'preparar', + 'café com leite', + 'Сырники', + 'Preparar café e creme', + 'preparação de cafe com leite', ]; - const TestCaseOption = Parse.Object.extend("TestCaseOption"); + const TestCaseOption = Parse.Object.extend('TestCaseOption'); const objects = []; for (const i in subjects) { const obj = new TestCaseOption({ casesensitive_comment: subjects[i] }); @@ -2166,28 +2163,28 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestCaseOption); - q.fullText("casesensitive_comment", "Preparar", { + q.fullText('casesensitive_comment', 'Preparar', { caseSensitive: true, }); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); }); }); - it("can perform a full text search with diacritic sensitive options", () => { + it('can perform a full text search with diacritic sensitive options', () => { const subjects = [ - "café", - "loja de café", - "preparando um café", - "Preparar", - "café com leite", - "Сырники", - "preparar café e creme", - "preparação de cafe com leite", + 'café', + 'loja de café', + 'preparando um café', + 'Preparar', + 'café com leite', + 'Сырники', + 'preparar café e creme', + 'preparação de cafe com leite', ]; - const TestDiacriticOption = Parse.Object.extend("TestDiacriticOption"); + const TestDiacriticOption = Parse.Object.extend('TestDiacriticOption'); const objects = []; for (const i in subjects) { const obj = new TestDiacriticOption({ diacritic_comment: subjects[i] }); @@ -2196,24 +2193,17 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestDiacriticOption); - q.fullText("diacritic_comment", "cafe", { diacriticSensitive: true }); + q.fullText('diacritic_comment', 'cafe', { diacriticSensitive: true }); return q.find(); }) - .then((results) => { + .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 TestCaseDiacriticOption = Parse.Object.extend( - "TestCaseDiacriticOption" - ); + 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 TestCaseDiacriticOption = Parse.Object.extend('TestCaseDiacriticOption'); const objects = []; for (const i in subjects) { const obj = new TestCaseDiacriticOption({ @@ -2224,31 +2214,28 @@ describe("Parse Query", () => { return Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestCaseDiacriticOption); - q.fullText("diacritic_comment", "cafe", { + q.fullText('diacritic_comment', 'cafe', { caseSensitive: true, diacriticSensitive: true, }); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal( - results[0].get("diacritic_comment"), - "preparação de cafe com leite" - ); + 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é", - "preparando um café", - "preparar", - "café com leite", - "Сырники", - "prepare café e creme", - "preparação de cafe com leite", + 'café', + 'loja de café', + 'preparando um café', + 'preparar', + 'café com leite', + 'Сырники', + 'prepare café e creme', + 'preparação de cafe com leite', ]; const objects = []; for (const i in subjects) { @@ -2258,8 +2245,8 @@ describe("Parse Query", () => { Parse.Object.saveAll(objects) .then(() => { const q = new Parse.Query(TestObject); - q.fullText("comment", "preparar", { - language: "portuguese", + q.fullText('comment', 'preparar', { + language: 'portuguese', notAnOption: true, }); return q.find(); @@ -2269,10 +2256,10 @@ describe("Parse Query", () => { }); }); - it("can return results in map", async () => { - const obj1 = new TestObject({ foo: "bar" }); - const obj2 = new TestObject({ foo: "baz" }); - const obj3 = new TestObject({ foo: "bin" }); + it('can return results in map', async () => { + const obj1 = new TestObject({ foo: 'bar' }); + const obj2 = new TestObject({ foo: 'baz' }); + const obj3 = new TestObject({ foo: 'bin' }); await Parse.Object.saveAll([obj1, obj2, obj3]); let i = 0; const mapQuery = new Parse.Query(TestObject); @@ -2280,18 +2267,18 @@ describe("Parse Query", () => { assert.equal(index, i); assert.equal(query, mapQuery); i += 1; - return object.get("foo"); + return object.get('foo'); }); - assert.equal(results.includes("bar"), true); - assert.equal(results.includes("baz"), true); - assert.equal(results.includes("bin"), true); + assert.equal(results.includes('bar'), true); + assert.equal(results.includes('baz'), true); + assert.equal(results.includes('bin'), true); assert.equal(results.length, 3); }); - it("can return results in filter", async () => { - const obj1 = new TestObject({ foo: "bar" }); - const obj2 = new TestObject({ foo: "baz" }); - const obj3 = new TestObject({ foo: "bin" }); + it('can return results in filter', async () => { + const obj1 = new TestObject({ foo: 'bar' }); + const obj2 = new TestObject({ foo: 'baz' }); + const obj3 = new TestObject({ foo: 'bin' }); await Parse.Object.saveAll([obj1, obj2, obj3]); let i = 0; const filterQuery = new Parse.Query(TestObject); @@ -2299,13 +2286,13 @@ describe("Parse Query", () => { assert.equal(index, i); assert.equal(query, filterQuery); i += 1; - return object.get("foo") === "bar"; + return object.get('foo') === 'bar'; }); - assert.equal(results[0].get("foo"), "bar"); + assert.equal(results[0].get('foo'), 'bar'); assert.equal(results.length, 1); }); - it("can return results in reduce", async () => { + it('can return results in reduce', async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); @@ -2315,52 +2302,49 @@ describe("Parse Query", () => { const result = await reduceQuery.reduce((accumulator, object, index) => { assert.equal(index, i); i += 1; - return accumulator + object.get("number"); + return accumulator + object.get('number'); }, 0); assert.equal(result, 6); }); - it("can cancel query", async () => { + it('can cancel query', async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); 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(); }); - it("can query with hint", async () => { + it('can query with hint', async () => { const obj1 = new TestObject({ number: 1 }); const obj2 = new TestObject({ number: 2 }); const obj3 = new TestObject({ number: 3 }); await Parse.Object.saveAll([obj1, obj2, obj3]); const query = new Parse.Query(TestObject); - query.hint("_id_"); + query.hint('_id_'); query.explain(); const explain = await query.find(); - assert.equal( - explain.queryPlanner.winningPlan.inputStage.inputStage.indexName, - "_id_" - ); + assert.equal(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName, '_id_'); }); - it("can query with select on null field", async () => { + it('can query with select on null field', async () => { const obj1 = new TestObject({ number: 1, arrayField: [] }); const obj2 = new TestObject({ number: 2, arrayField: [{ subfield: 1 }] }); const obj3 = new TestObject({ number: 3, arrayField: null }); await Parse.Object.saveAll([obj1, obj2, obj3]); const query = new Parse.Query(TestObject); - query.select(["arrayField.subfield"]); - query.ascending("number"); + query.select(['arrayField.subfield']); + query.ascending('number'); const results = await query.find(); - expect(results[0].get("arrayField")).toEqual([]); - expect(results[1].get("arrayField")).toEqual([{ subfield: 1 }]); - expect(results[2].get("arrayField")).toEqual(null); + expect(results[0].get('arrayField')).toEqual([]); + expect(results[1].get('arrayField')).toEqual([{ subfield: 1 }]); + expect(results[2].get('arrayField')).toEqual(null); }); }); diff --git a/integration/test/ParseRelationTest.js b/integration/test/ParseRelationTest.js index 57c76e65a..05fbeb193 100644 --- a/integration/test/ParseRelationTest.js +++ b/integration/test/ParseRelationTest.js @@ -1,23 +1,23 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Parse Relation", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Relation', () => { + beforeEach(done => { + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(() => { done(); }); }); - it("can do a simple add and remove", (done) => { - const ChildObject = Parse.Object.extend("ChildObject"); + 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 })); @@ -26,37 +26,37 @@ describe("Parse Relation", () => { let parent = null; Parse.Object.saveAll(childObjects) .then(() => { - parent = new Parse.Object("ParentObject"); - parent.set("x", 4); - rel = parent.relation("child"); + 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")); + .then(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); return rel.query().find(); }) - .then((results) => { + .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")); + .then(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); return rel.query().find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 0); done(); }); }); - it("can query relation without schema", (done) => { - const ChildObject = Parse.Object.extend("ChildObject"); + 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 })); @@ -64,26 +64,26 @@ describe("Parse Relation", () => { let parent = null; Parse.Object.saveAll(childObjects) .then(() => { - parent = new Parse.Object("ParentObject"); - parent.set("x", 4); - const rel = parent.relation("child"); + 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(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); + return parentAgain.relation('child').query().find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); assert.equal(results[0].id, childObjects[0].id); done(); }); }); - it("can compound add and remove operations", (done) => { - const ChildObject = Parse.Object.extend("ChildObject"); + 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 })); @@ -92,9 +92,9 @@ describe("Parse Relation", () => { let rel = null; Parse.Object.saveAll(childObjects) .then(() => { - parent = new Parse.Object("ParentObject"); - parent.set("x", 4); - rel = parent.relation("child"); + 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]); @@ -104,7 +104,7 @@ describe("Parse Relation", () => { .then(() => { return rel.query().find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); rel.remove(childObjects[1]); @@ -117,159 +117,159 @@ describe("Parse Relation", () => { .then(() => { return rel.query().find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); done(); }); }); - it("can refine relation queries", (done) => { - const ChildObject = Parse.Object.extend("ChildObject"); + 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 })); } Parse.Object.saveAll(childObjects) .then(() => { - const parent = new Parse.Object("ParentObject"); - parent.set("x", 4); - const rel = parent.relation("child"); + 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); + .then(parentAgain => { + const q = parentAgain.relation('child').query(); + q.equalTo('x', 2); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); assert.equal(results[0].id, childObjects[2].id); done(); }); }); - it("can query relation fields", (done) => { - const ChildObject = Parse.Object.extend("ChildObject"); + 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 })); } Parse.Object.saveAll(childObjects) .then(() => { - const parent = new Parse.Object("ParentObject"); - parent.set("x", 4); - const rel = parent.relation("child"); + 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"); + 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 q = new Parse.Query('ParentObject'); const objects = [childObjects[4], childObjects[9]]; - q.containedIn("child", objects); + q.containedIn('child', objects); return q.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].get("x"), 3); + assert.equal(results[0].get('x'), 3); 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"); + 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"); + const relation = car.relation('wheels'); relation.add(origWheel); return car.save(); }) - .then((car) => { + .then(car => { const unfetchedCar = new Car(); unfetchedCar.id = car.id; - const relation = unfetchedCar.relation("wheels"); + const relation = unfetchedCar.relation('wheels'); const query = relation.query(); return query.get(origWheel.id); }) - .then((wheel) => { - assert.equal(wheel.className, "Wheel"); + .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) => { - const Wheel = Parse.Object.extend("Wheel"); - const Car = Parse.Object.extend("Car"); + 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"); + const relation = car.relation('wheels'); relation.add(origWheel); return car.save(); }) - .then((car) => { + .then(car => { const unfetchedCar = new Car(); unfetchedCar.id = car.id; - const relation = unfetchedCar.relation("wheels"); + const relation = unfetchedCar.relation('wheels'); const query = relation.query(); return query.find(); }) - .then((wheels) => { + .then(wheels => { assert.equal(wheels.length, 1); - assert.equal(wheels[0].className, "Wheel"); + assert.equal(wheels[0].className, 'Wheel'); assert.equal(wheels[0].id, origWheel.id); done(); }); }); - it("can add empty array to relation", async () => { + it('can add empty array to relation', async () => { const object1 = new TestObject(); await object1.save(); const object2 = new TestObject(); - object2.relation("related").add(object1); + object2.relation('related').add(object1); await object2.save(); - object2.relation("related").add([]); + object2.relation('related').add([]); await object2.save(); - const relation = object2.relation("related"); + const relation = object2.relation('related'); const query = relation.query(); const results = await query.find(); expect(results.length).toBe(1); }); - it("can remove empty array from relation", async () => { + it('can remove empty array from relation', async () => { const object1 = new TestObject(); await object1.save(); const object2 = new TestObject(); - object2.relation("related").add(object1); + object2.relation('related').add(object1); await object2.save(); - object2.relation("related").remove([]); + object2.relation('related').remove([]); await object2.save(); - const relation = object2.relation("related"); + const relation = object2.relation('related'); const query = relation.query(); const results = await query.find(); expect(results.length).toBe(1); diff --git a/integration/test/ParseRoleTest.js b/integration/test/ParseRoleTest.js index 61aa72c4a..d5174a3e4 100644 --- a/integration/test/ParseRoleTest.js +++ b/integration/test/ParseRoleTest.js @@ -1,11 +1,11 @@ -"use strict"; +'use strict'; /* eslint-disable no-unused-vars */ -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); function privateTo(someone) { const acl = new Parse.ACL(); @@ -23,12 +23,12 @@ function publicAccess() { function createUser(username) { const user = new Parse.User(); - user.set("username", username); - user.set("password", username); + user.set('username', username); + user.set('password', username); return user; } -describe("Parse Role", () => { +describe('Parse Role', () => { /** TODO: Implement these. There was some bugginess related to parse-server. **/ }); diff --git a/integration/test/ParseSchemaTest.js b/integration/test/ParseSchemaTest.js index 49e824b8e..dfa48a240 100644 --- a/integration/test/ParseSchemaTest.js +++ b/integration/test/ParseSchemaTest.js @@ -1,6 +1,6 @@ -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); const emptyCLPS = { find: {}, @@ -14,31 +14,31 @@ const emptyCLPS = { }; const defaultCLPS = { - find: { "*": true }, - count: { "*": true }, - get: { "*": true }, - create: { "*": true }, - update: { "*": true }, - delete: { "*": true }, - addField: { "*": true }, - protectedFields: { "*": [] }, + find: { '*': true }, + count: { '*': true }, + get: { '*': true }, + create: { '*': true }, + update: { '*': true }, + delete: { '*': true }, + addField: { '*': true }, + protectedFields: { '*': [] }, }; -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); -describe("Schema", () => { +describe('Schema', () => { beforeAll(() => { - Parse.initialize("integration"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); - Parse.CoreManager.set("MASTER_KEY", "notsosecret"); + Parse.initialize('integration'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); + Parse.CoreManager.set('MASTER_KEY', 'notsosecret'); Parse.Storage._clear(); }); - beforeEach((done) => { + beforeEach(done => { clear().then(done); }); - it("invalid get all no schema", (done) => { + it('invalid get all no schema', done => { Parse.Schema.all() .then(() => {}) .catch(() => { @@ -46,8 +46,8 @@ describe("Schema", () => { }); }); - it("invalid get no schema", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid get no schema', done => { + const testSchema = new Parse.Schema('SchemaTest'); testSchema .get() .then(() => {}) @@ -56,110 +56,104 @@ describe("Schema", () => { }); }); - it("save", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); - testSchema.save().then((result) => { - assert.equal(result.className, "SchemaTest"); + it('save', done => { + const testSchema = new Parse.Schema('SchemaTest'); + testSchema.save().then(result => { + assert.equal(result.className, 'SchemaTest'); done(); }); }); - it("get", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('get', done => { + const testSchema = new Parse.Schema('SchemaTest'); testSchema - .addField("defaultFieldString") - .addString("stringField") - .addNumber("numberField") - .addBoolean("booleanField") - .addDate("dateField") - .addFile("fileField") - .addGeoPoint("geoPointField") - .addPolygon("polygonField") - .addArray("arrayField") - .addObject("objectField") - .addPointer("pointerField", "_User") - .addRelation("relationField", "_User"); + .addField('defaultFieldString') + .addString('stringField') + .addNumber('numberField') + .addBoolean('booleanField') + .addDate('dateField') + .addFile('fileField') + .addGeoPoint('geoPointField') + .addPolygon('polygonField') + .addArray('arrayField') + .addObject('objectField') + .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"); + .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) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('all', done => { + const testSchema = new Parse.Schema('SchemaTest'); testSchema .save() .then(() => { return Parse.Schema.all(); }) - .then((results) => { + .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", { + it('save required and default values', async () => { + const testSchema = new Parse.Schema('SchemaTest'); + testSchema.addField('fieldString', 'String', { required: true, - defaultValue: "Hello World", + defaultValue: 'Hello World', }); const schema = await testSchema.save(); assert.deepEqual(schema.fields.fieldString, { - type: "String", + type: 'String', required: true, - defaultValue: "Hello World", + defaultValue: 'Hello World', }); - const object = new Parse.Object("SchemaTest"); + const object = new Parse.Object('SchemaTest'); await object.save(); - assert.equal(object.get("fieldString"), "Hello World"); + assert.equal(object.get('fieldString'), 'Hello World'); }); - it("save required and default pointer values", async () => { + it('save required and default pointer values', async () => { const pointer = new TestObject(); await pointer.save(); - const testSchema = new Parse.Schema("SchemaTest"); + const testSchema = new Parse.Schema('SchemaTest'); testSchema - .addPointer("pointerField", "TestObject", { + .addPointer('pointerField', 'TestObject', { required: true, defaultValue: pointer, }) - .addPointer("pointerJSONField", "TestObject", { + .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() - ); + assert.deepEqual(schema.fields.pointerField, schema.fields.pointerJSONField); + assert.deepEqual(schema.fields.pointerField.defaultValue, pointer.toPointer()); assert.equal(schema.fields.pointerField.required, true); }); - it("set multiple required and default values", async () => { + it('set multiple required and default values', async () => { const point = new Parse.GeoPoint(44.0, -11.0); const polygon = new Parse.Polygon([ [0, 0], @@ -167,78 +161,78 @@ describe("Schema", () => { [1, 1], [1, 0], ]); - const file = new Parse.File("parse-server-logo", { base64: "ParseA==" }); + const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); await file.save(); - const testSchema = new Parse.Schema("SchemaFieldTest"); + const testSchema = new Parse.Schema('SchemaFieldTest'); testSchema - .addField("defaultFieldString", "String", { + .addField('defaultFieldString', 'String', { required: true, - defaultValue: "hello", + defaultValue: 'hello', }) - .addString("stringField", { required: true, defaultValue: "world" }) - .addNumber("numberField", { required: true, defaultValue: 10 }) - .addBoolean("booleanField", { required: true, defaultValue: false }) - .addDate("dateField", { + .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"), + defaultValue: new Date('2000-01-01T00:00:00.000Z'), }) - .addDate("dateStringField", { + .addDate('dateStringField', { required: true, - defaultValue: "2000-01-01T00:00:00.000Z", + 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", { + .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" }, + defaultValue: { foo: 'bar' }, }); const schema = await testSchema.save(); assert.deepEqual(schema.fields, { - objectId: { type: "String" }, - updatedAt: { type: "Date" }, - createdAt: { type: "Date" }, + objectId: { type: 'String' }, + updatedAt: { type: 'Date' }, + createdAt: { type: 'Date' }, defaultFieldString: { - type: "String", + type: 'String', required: true, - defaultValue: "hello", + defaultValue: 'hello', }, - stringField: { type: "String", required: true, defaultValue: "world" }, - numberField: { type: "Number", required: true, defaultValue: 10 }, - booleanField: { type: "Boolean", required: true, defaultValue: false }, + stringField: { type: 'String', required: true, defaultValue: 'world' }, + numberField: { type: 'Number', required: true, defaultValue: 10 }, + booleanField: { type: 'Boolean', required: true, defaultValue: false }, dateField: { - type: "Date", + type: 'Date', required: true, - defaultValue: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, + defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, }, dateStringField: { - type: "Date", + type: 'Date', required: true, - defaultValue: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, + defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, }, - fileField: { type: "File", required: true, defaultValue: file.toJSON() }, + fileField: { type: 'File', required: true, defaultValue: file.toJSON() }, geoPointField: { - type: "GeoPoint", + type: 'GeoPoint', required: true, defaultValue: point.toJSON(), }, polygonField: { - type: "Polygon", + type: 'Polygon', required: true, defaultValue: polygon.toJSON(), }, - arrayField: { type: "Array", required: true, defaultValue: [1, 2, 3] }, + arrayField: { type: 'Array', required: true, defaultValue: [1, 2, 3] }, objectField: { - type: "Object", + type: 'Object', required: true, - defaultValue: { foo: "bar" }, + defaultValue: { foo: 'bar' }, }, - ACL: { type: "ACL" }, + ACL: { type: 'ACL' }, }); - const object = new Parse.Object("SchemaFieldTest"); + const object = new Parse.Object('SchemaFieldTest'); await object.save(); const json = object.toJSON(); delete json.createdAt; @@ -246,16 +240,16 @@ describe("Schema", () => { delete json.objectId; const expected = { - defaultFieldString: "hello", - stringField: "world", + defaultFieldString: 'hello', + stringField: 'world', numberField: 10, booleanField: false, - dateField: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, - dateStringField: { __type: "Date", iso: "2000-01-01T00:00:00.000Z" }, + dateField: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, + dateStringField: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, fileField: file.toJSON(), geoPointField: point.toJSON(), polygonField: { - __type: "Polygon", + __type: 'Polygon', coordinates: [ [0, 0], [0, 1], @@ -265,40 +259,40 @@ describe("Schema", () => { ], }, arrayField: [1, 2, 3], - objectField: { foo: "bar" }, + objectField: { foo: 'bar' }, }; assert.deepEqual(json, expected); }); - it("save class level permissions", async () => { + it('save class level permissions', async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { "*": true }, + create: { '*': true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, protectedFields: {}, }; - const testSchema = new Parse.Schema("SchemaTest"); + const testSchema = new Parse.Schema('SchemaTest'); testSchema.setCLP(clp); const schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, clp); }); - it("update class level permissions", async () => { + it('update class level permissions', async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { "*": true }, + create: { '*': true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, protectedFields: {}, }; - const testSchema = new Parse.Schema("SchemaTest"); + const testSchema = new Parse.Schema('SchemaTest'); let schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, defaultCLPS); @@ -315,18 +309,18 @@ describe("Schema", () => { assert.deepEqual(schema.classLevelPermissions, emptyCLPS); }); - it("update class level permissions multiple", async () => { + it('update class level permissions multiple', async () => { const clp = { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { "*": true }, + create: { '*': true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, protectedFields: {}, }; - const testSchema = new Parse.Schema("SchemaTest"); + const testSchema = new Parse.Schema('SchemaTest'); testSchema.setCLP(clp); let schema = await testSchema.save(); assert.deepEqual(schema.classLevelPermissions, clp); @@ -338,31 +332,31 @@ describe("Schema", () => { assert.deepEqual(schema.classLevelPermissions, clp); }); - it("update", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); - testSchema.addString("name"); + it('update', done => { + const testSchema = new Parse.Schema('SchemaTest'); + testSchema.addString('name'); testSchema .save() .then(() => { - testSchema.deleteField("name"); - testSchema.addNumber("quantity"); - testSchema.addBoolean("status"); + 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"); + .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) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('multiple update', done => { + const testSchema = new Parse.Schema('SchemaTest'); testSchema .save() .then(() => { - testSchema.addString("name"); + testSchema.addString('name'); return testSchema.update(); }) .then(() => { @@ -371,15 +365,15 @@ describe("Schema", () => { .then(() => { return testSchema.get(); }) - .then((result) => { + .then(result => { assert.equal(Object.keys(result.fields).length, 5); done(); }); }); - it("delete", (done) => { - const testSchema1 = new Parse.Schema("SchemaTest1"); - const testSchema2 = new Parse.Schema("SchemaTest2"); + it('delete', done => { + const testSchema1 = new Parse.Schema('SchemaTest1'); + const testSchema2 = new Parse.Schema('SchemaTest2'); testSchema1 .save() .then(() => { @@ -388,23 +382,23 @@ describe("Schema", () => { .then(() => { return Parse.Schema.all(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 2); return testSchema1.delete(); }) .then(() => { return Parse.Schema.all(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); - assert.equal(results[0].className, "SchemaTest2"); + assert.equal(results[0].className, 'SchemaTest2'); done(); }); }); - it("purge", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); - const obj = new Parse.Object("SchemaTest"); + it('purge', done => { + const testSchema = new Parse.Schema('SchemaTest'); + const obj = new Parse.Object('SchemaTest'); obj .save() .then(() => { @@ -414,11 +408,11 @@ describe("Schema", () => { // Should never reach here assert.equal(true, false); }) - .catch((error) => { + .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." + 'Class SchemaTest is not empty, contains 1 objects, cannot drop schema.' ); return Promise.resolve(); }); @@ -427,10 +421,10 @@ describe("Schema", () => { return testSchema.purge(); }) .then(() => { - const query = new Parse.Query("SchemaTest"); + const query = new Parse.Query('SchemaTest'); return query.count(); }) - .then((count) => { + .then(count => { assert.equal(count, 0); // Delete only works on empty schema, extra check return testSchema.delete(); @@ -440,62 +434,62 @@ describe("Schema", () => { }); }); - it("save index", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('save index', done => { + const testSchema = new Parse.Schema('SchemaTest'); const index = { name: 1, }; - testSchema.addString("name"); - testSchema.addIndex("test_index", index); - testSchema.save().then((result) => { + testSchema.addString('name'); + testSchema.addIndex('test_index', index); + testSchema.save().then(result => { assert.notEqual(result.indexes.test_index, undefined); done(); }); }); - it("update index", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + 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); + testSchema.addString('name'); + testSchema.addIndex('test_index', index); return testSchema.update(); }) - .then((result) => { + .then(result => { assert.notEqual(result.indexes.test_index, undefined); done(); }); }); - it("delete index", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + 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); + testSchema.addString('name'); + testSchema.addIndex('test_index', index); return testSchema.update(); }) - .then((result) => { + .then(result => { assert.notEqual(result.indexes.test_index, undefined); - testSchema.deleteIndex("test_index"); + testSchema.deleteIndex('test_index'); return testSchema.update(); }) - .then((result) => { + .then(result => { assert.equal(result.indexes.test_index, undefined); done(); }); }); - it("invalid field name", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid field name', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addField(null); } catch (e) { @@ -503,17 +497,17 @@ describe("Schema", () => { } }); - it("invalid field type", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid field type', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { - testSchema.addField("name", "UnknownType"); + testSchema.addField('name', 'UnknownType'); } catch (e) { done(); } }); - it("invalid index name", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid index name', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addIndex(null); } catch (e) { @@ -521,17 +515,17 @@ describe("Schema", () => { } }); - it("invalid index", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid index', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { - testSchema.addIndex("name", null); + testSchema.addIndex('name', null); } catch (e) { done(); } }); - it("invalid pointer name", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid pointer name', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addPointer(null); } catch (e) { @@ -539,17 +533,17 @@ describe("Schema", () => { } }); - it("invalid pointer class", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid pointer class', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { - testSchema.addPointer("name", null); + testSchema.addPointer('name', null); } catch (e) { done(); } }); - it("invalid relation name", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid relation name', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addRelation(null); } catch (e) { @@ -557,16 +551,16 @@ describe("Schema", () => { } }); - it("invalid relation class", (done) => { - const testSchema = new Parse.Schema("SchemaTest"); + it('invalid relation class', done => { + const testSchema = new Parse.Schema('SchemaTest'); try { - testSchema.addRelation("name", null); + testSchema.addRelation('name', null); } catch (e) { done(); } }); - 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 130956f2c..ef7a17bc4 100644 --- a/integration/test/ParseSubclassTest.js +++ b/integration/test/ParseSubclassTest.js @@ -1,19 +1,19 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -describe("Parse Object Subclasses", () => { - beforeEach((done) => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); +describe('Parse Object Subclasses', () => { + 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) => { - const Subclass = Parse.Object.extend("Subclass", { + it('uses subclasses when doing query find', done => { + const Subclass = Parse.Object.extend('Subclass', { initialize(attributes, options, number) { this.number = number || -1; }, @@ -27,7 +27,7 @@ describe("Parse Object Subclasses", () => { const query = new Parse.Query(Subclass); return query.find(); }) - .then((results) => { + .then(results => { assert.equal(results.length, 1); assert(results[0] instanceof Subclass); assert.equal(results[0].number, -1); @@ -35,8 +35,8 @@ describe("Parse Object Subclasses", () => { }); }); - it("uses subclasses when doing query get", (done) => { - const Subclass = Parse.Object.extend("Subclass", { + it('uses subclasses when doing query get', done => { + const Subclass = Parse.Object.extend('Subclass', { initialize(attributes, options, number) { this.number = number || -1; }, @@ -50,34 +50,34 @@ describe("Parse Object Subclasses", () => { const query = new Parse.Query(Subclass); return query.get(object.id); }) - .then((result) => { + .then(result => { assert(result instanceof Subclass); assert.equal(result.number, -1); 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"); + 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" }) + .save({ foo: 'bar' }) .then(() => { const container = new Container(); return container.save({ items: [item] }); }) - .then((container) => { + .then(container => { const query = new Parse.Query(Container); return query.get(container.id); }) - .then((container) => { + .then(container => { assert(container instanceof Container); - assert.equal(container.get("items").length, 1); - const item = container.get("items")[0]; + 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); @@ -85,8 +85,8 @@ describe("Parse Object Subclasses", () => { }); }); - it("can subclass multiple levels explicitly", (done) => { - const Parent = Parse.Object.extend("MyClass", { + it('can subclass multiple levels explicitly', done => { + const Parent = Parse.Object.extend('MyClass', { initialize() { Parent.__super__.initialize.apply(this, arguments); this.parent = true; @@ -115,7 +115,7 @@ describe("Parse Object Subclasses", () => { const query = new Parse.Query(Grandchild); return query.get(object.id); }) - .then((result) => { + .then(result => { assert(result instanceof Parent); assert(result instanceof Child); assert(result instanceof Grandchild); @@ -126,22 +126,22 @@ describe("Parse Object Subclasses", () => { }); }); - it("can subclass multiple levels implicitly", (done) => { - const Parent = Parse.Object.extend("MyClass", { + 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", { + const Child = Parse.Object.extend('MyClass', { initialize() { Child.__super__.initialize.apply(this, arguments); this.child = true; }, }); - const Grandchild = Parse.Object.extend("MyClass", { + const Grandchild = Parse.Object.extend('MyClass', { initialize() { Grandchild.__super__.initialize.apply(this, arguments); this.grandchild = true; @@ -156,7 +156,7 @@ describe("Parse Object Subclasses", () => { const query = new Parse.Query(Grandchild); return query.get(object.id); }) - .then((result) => { + .then(result => { assert(result instanceof Parent); assert(result instanceof Child); assert(result instanceof Grandchild); @@ -167,10 +167,10 @@ describe("Parse Object Subclasses", () => { }); }); - it("can subclass multiple levels explicitly with different names", (done) => { - const Parent = Parse.Object.extend("MyClass"); + 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 Grandchild = Child.extend('NewClass'); const object = new Parent(); @@ -180,7 +180,7 @@ describe("Parse Object Subclasses", () => { const query = new Parse.Query(Child); return query.get(object.id); }) - .then((result) => { + .then(result => { assert(result instanceof Parent); assert(result instanceof Child); @@ -193,11 +193,11 @@ describe("Parse Object Subclasses", () => { }); }); - it("propagates instance properties", () => { - const Squirtle = Parse.Object.extend("Squirtle", { + it('propagates instance properties', () => { + const Squirtle = Parse.Object.extend('Squirtle', { water: true, }); - const Wartortle = Squirtle.extend("Wartortle"); + const Wartortle = Squirtle.extend('Wartortle'); const wartortle = new Wartortle(); assert(wartortle.water); }); diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index 99c71c3c1..21dba77c1 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -1,10 +1,10 @@ -"use strict"; +'use strict'; -const assert = require("assert"); -const clear = require("./clear"); -const Parse = require("../../node"); +const assert = require('assert'); +const clear = require('./clear'); +const Parse = require('../../node'); -const TestObject = Parse.Object.extend("TestObject"); +const TestObject = Parse.Object.extend('TestObject'); class CustomUser extends Parse.User { constructor(attributes) { @@ -15,16 +15,16 @@ class CustomUser extends Parse.User { return 5; } } -Parse.Object.registerSubclass("CustomUser", CustomUser); +Parse.Object.registerSubclass('CustomUser', CustomUser); const provider = { authenticate: () => Promise.resolve(), restoreAuthentication: () => true, - getAuthType: () => "anonymous", + getAuthType: () => 'anonymous', getAuthData() { return { authData: { - id: "1234", + id: '1234', }, }; }, @@ -32,27 +32,27 @@ const provider = { Parse.User._registerAuthenticationProvider(provider); const authResponse = { - userID: "test", - accessToken: "test", - expiresIn: "test", // Should be unix timestamp + userID: 'test', + accessToken: 'test', + expiresIn: 'test', // Should be unix timestamp }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, getAuthResponse: () => authResponse, }; -describe("Parse User", () => { +describe('Parse User', () => { beforeAll(() => { - Parse.initialize("integration", null, "notsosecret"); - Parse.CoreManager.set("SERVER_URL", "http://localhost:1337/parse"); + Parse.initialize('integration', null, 'notsosecret'); + Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - Parse.Object.registerSubclass("_User", Parse.User); + Parse.Object.registerSubclass('_User', Parse.User); }); - beforeEach((done) => { + beforeEach(done => { let promise = Promise.resolve(); try { promise = Parse.User.logOut(); @@ -68,114 +68,112 @@ describe("Parse User", () => { }); }); - 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.setPassword('asdf'); + user.setUsername('zxcv'); + 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") + it('fails log in with wrong username', done => { + Parse.User.signUp('asdf', 'zxcv') .then(() => { - return Parse.User.logIn("false_user", "asdf3"); + return Parse.User.logIn('false_user', 'asdf3'); }) .then(null, () => { done(); }); }); - it("fails log in with wrong password", (done) => { - Parse.User.signUp("asdf", "zxcv") + it('fails log in with wrong password', done => { + Parse.User.signUp('asdf', 'zxcv') .then(() => { - return Parse.User.logIn("asdf", "asdfWrong"); + return Parse.User.logIn('asdf', 'asdfWrong'); }) .then(null, () => { done(); }); }); - it("can log in a user", (done) => { - Parse.User.signUp("asdf", "zxcv") + it('can log in a user', done => { + Parse.User.signUp('asdf', 'zxcv') .then(() => { - return Parse.User.logIn("asdf", "zxcv"); + return Parse.User.logIn('asdf', 'zxcv'); }) - .then((user) => { - assert.equal(user.get("username"), "asdf"); + .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") + it('can log in a user using POST method', done => { + Parse.User.signUp('asdf', 'zxcv') .then(() => { - return Parse.User.logIn("asdf", "zxcv", { usePost: true }); + return Parse.User.logIn('asdf', 'zxcv', { usePost: true }); }) - .then((user) => { - assert.equal(user.get("username"), "asdf"); + .then(user => { + assert.equal(user.get('username'), 'asdf'); expect(user.existed()).toBe(true); done(); }); }); - it("can login users with installationId", async () => { + it('can login users with installationId', async () => { Parse.User.enableUnsafeCurrentUser(); const currentInstallation = await Parse.CoreManager.getInstallationController().currentInstallationId(); - const installationId = "12345678"; + const installationId = '12345678'; const user = new Parse.User(); - user.set("username", "parse"); - user.set("password", "mypass"); + user.set('username', 'parse'); + user.set('password', 'mypass'); await user.signUp(null, { installationId }); const query = new Parse.Query(Parse.Session); - query.equalTo("user", user); + query.equalTo('user', user); const result = await query.first({ useMasterKey: true }); - expect(result.get("installationId")).toBe(installationId); - expect(result.get("sessionToken")).toBe(user.getSessionToken()); + expect(result.get('installationId')).toBe(installationId); + expect(result.get('sessionToken')).toBe(user.getSessionToken()); // Should not clean up sessions - const loggedUser = await Parse.User.logIn("parse", "mypass"); + const loggedUser = await Parse.User.logIn('parse', 'mypass'); const sessionQuery = new Parse.Query(Parse.Session); let sessions = await sessionQuery.find({ useMasterKey: true }); expect(sessions.length).toBe(2); - expect(sessions[0].get("installationId")).toBe(installationId); - expect(sessions[1].get("installationId")).toBe(currentInstallation); - expect(sessions[0].get("sessionToken")).toBe(user.getSessionToken()); - expect(sessions[1].get("sessionToken")).toBe(loggedUser.getSessionToken()); + expect(sessions[0].get('installationId')).toBe(installationId); + expect(sessions[1].get('installationId')).toBe(currentInstallation); + expect(sessions[0].get('sessionToken')).toBe(user.getSessionToken()); + expect(sessions[1].get('sessionToken')).toBe(loggedUser.getSessionToken()); // Should clean up sessions - const installationUser = await Parse.User.logIn("parse", "mypass", { + 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); - expect(sessions[1].get("installationId")).toBe(installationId); - expect(sessions[0].get("sessionToken")).toBe(loggedUser.getSessionToken()); - expect(sessions[1].get("sessionToken")).toBe( - installationUser.getSessionToken() - ); + expect(sessions[0].get('installationId')).toBe(currentInstallation); + expect(sessions[1].get('installationId')).toBe(installationId); + expect(sessions[0].get('sessionToken')).toBe(loggedUser.getSessionToken()); + 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) => { + Parse.User.signUp('jason', 'parse', { code: 'red' }) + .then(user => { newUser = user; assert.equal(Parse.User.current(), newUser); session = newUser.getSessionToken(); @@ -188,118 +186,118 @@ describe("Parse User", () => { return Parse.User.become(session); }) - .then((user) => { + .then(user => { assert.equal(Parse.User.current(), user); assert(user); assert.equal(user.id, newUser.id); - assert.equal(user.get("code"), "red"); + assert.equal(user.get('code'), 'red'); return Parse.User.logOut(); }) .then(() => { assert(!Parse.User.current()); - return Parse.User.become("garbage"); + 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({ - password: "asdf", - email: "asdf@example.com", - username: "zxcv", + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', }); user .signUp() - .then((userAgain) => { + .then(userAgain => { assert.equal(user, userAgain); const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((userNotAuthed) => { + .then(userNotAuthed => { notAuthed = userNotAuthed; user = new Parse.User(); user.set({ - username: "hacker", - password: "password", + username: 'hacker', + password: 'password', }); return user.signUp(); }) - .then((userAgain) => { + .then(userAgain => { assert.equal(userAgain, user); - notAuthed.set("username", "changed"); + notAuthed.set('username', 'changed'); return notAuthed.save(); }) - .then(null, (e) => { + .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", + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', }) .then(() => { const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((userNotAuthed) => { + .then(userNotAuthed => { notAuthed = userNotAuthed; user = new Parse.User(); return user.signUp({ - username: "hacker", - password: "password", + username: 'hacker', + password: 'password', }); }) - .then((userAgain) => { + .then(userAgain => { assert.equal(userAgain, user); - notAuthed.set("username", "changed"); + notAuthed.set('username', 'changed'); return notAuthed.destroy(); }) - .then(null, (e) => { + .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", + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', }) .then(() => { const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((userNotAuthed) => { + .then(userNotAuthed => { notAuthed = userNotAuthed; user = new Parse.User(); return user.signUp({ - username: "hacker", - password: "password", + username: 'hacker', + password: 'password', }); }) .then(() => { const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((userNotAuthedNotChanged) => { - notAuthed.set("username", "changed"); + .then(userNotAuthedNotChanged => { + notAuthed.set('username', 'changed'); const object = new TestObject(); return object.save({ user: userNotAuthedNotChanged }); }) @@ -307,73 +305,73 @@ describe("Parse User", () => { const item1 = new TestObject(); return item1.save({ number: 0 }); }) - .then((item1) => { - item1.set("number", 1); + .then(item1 => { + item1.set('number', 1); const item2 = new TestObject(); - item2.set("number", 2); + item2.set('number', 2); return Parse.Object.saveAll([item1, item2, notAuthed]); }) - .then(null, (e) => { + .then(null, e => { assert.equal(e.code, Parse.Error.SESSION_MISSING); done(); }); }); - it("can fetch non-auth user with include", async () => { + it('can fetch non-auth user with include', async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object("TestObject"); - child.set("field", "test"); + const child = new Parse.Object('TestObject'); + child.set('field', 'test'); const user = new Parse.User(); - user.set("password", "asdf"); - user.set("email", "asdf@exxample.com"); - user.set("username", "zxcv"); - user.set("child", child); + user.set('password', 'asdf'); + user.set('email', 'asdf@exxample.com'); + user.set('username', 'zxcv'); + user.set('child', child); await user.signUp(); const query = new Parse.Query(Parse.User); const userNotAuthed = await query.get(user.id); - assert.equal(userNotAuthed.get("child").get("field"), undefined); + assert.equal(userNotAuthed.get('child').get('field'), undefined); - const fetchedUser = await userNotAuthed.fetchWithInclude("child"); + const fetchedUser = await userNotAuthed.fetchWithInclude('child'); - assert.equal(userNotAuthed.get("child").get("field"), "test"); - assert.equal(fetchedUser.get("child").get("field"), "test"); + assert.equal(userNotAuthed.get('child').get('field'), 'test'); + assert.equal(fetchedUser.get('child').get('field'), 'test'); }); - it("can fetch auth user with include", async () => { + it('can fetch auth user with include', async () => { Parse.User.enableUnsafeCurrentUser(); - const child = new Parse.Object("TestObject"); - child.set("field", "test"); + const child = new Parse.Object('TestObject'); + child.set('field', 'test'); let user = new Parse.User(); - user.set("password", "asdf"); - user.set("email", "asdf@exxample.com"); - user.set("username", "zxcv"); - user.set("child", child); + user.set('password', 'asdf'); + user.set('email', 'asdf@exxample.com'); + user.set('username', 'zxcv'); + user.set('child', child); await user.signUp(); - user = await Parse.User.logIn("zxcv", "asdf"); + user = await Parse.User.logIn('zxcv', 'asdf'); - assert.equal(user.get("child").get("field"), undefined); - assert.equal(Parse.User.current().get("child").get("field"), undefined); + assert.equal(user.get('child').get('field'), undefined); + assert.equal(Parse.User.current().get('child').get('field'), undefined); - const fetchedUser = await user.fetchWithInclude("child"); + const fetchedUser = await user.fetchWithInclude('child'); const current = await Parse.User.currentAsync(); - assert.equal(user.get("child").get("field"), "test"); - assert.equal(current.get("child").get("field"), "test"); - assert.equal(fetchedUser.get("child").get("field"), "test"); - assert.equal(Parse.User.current().get("child").get("field"), "test"); + assert.equal(user.get('child').get('field'), 'test'); + assert.equal(current.get('child').get('field'), 'test'); + assert.equal(fetchedUser.get('child').get('field'), 'test'); + 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.set('password', 'asdf'); + user.set('email', 'asdf@example.com'); + user.set('username', 'zxcv'); user .signUp() .then(() => { @@ -392,19 +390,19 @@ describe("Parse User", () => { }); }); - 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(); const user3 = new Parse.User(); - user1.set("username", "a"); - user2.set("username", "b"); - user3.set("username", "c"); + user1.set('username', 'a'); + user2.set('username', 'b'); + user3.set('username', 'c'); - user1.set("password", "password"); - user2.set("password", "password"); - user3.set("password", "password"); + user1.set('password', 'password'); + user2.set('password', 'password'); + user3.set('password', 'password'); user1 .signUp() @@ -427,21 +425,21 @@ describe("Parse User", () => { assert(!user2.isCurrent()); assert(user3.isCurrent()); - return Parse.User.logIn("a", "password"); + return Parse.User.logIn('a', 'password'); }) .then(() => { assert(user1.isCurrent()); assert(!user2.isCurrent()); assert(!user3.isCurrent()); - return Parse.User.logIn("b", "password"); + return Parse.User.logIn('b', 'password'); }) .then(() => { assert(!user1.isCurrent()); assert(user2.isCurrent()); assert(!user3.isCurrent()); - return Parse.User.logIn("c", "password"); + return Parse.User.logIn('c', 'password'); }) .then(() => { assert(!user1.isCurrent()); @@ -456,57 +454,57 @@ describe("Parse User", () => { }); }); - 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.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) => { + .then(u => { assert.equal(u.id, user.id); return new Parse.Query(Parse.User).find(); }) - .then((users) => { + .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.set('password', 'asdf'); + user.set('email', 'asdf@example.com'); + user.set('username', 'zxcv'); user .signUp() .then(() => { - assert(user.has("sessionToken")); + assert(user.has('sessionToken')); const query = new Parse.Query(Parse.User); return query.get(user.id); }) - .then((u) => { + .then(u => { // Old object maintains token - assert(user.has("sessionToken")); + assert(user.has('sessionToken')); // New object doesn't have token - assert(!u.has("sessionToken")); + 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", + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', }) .then(() => { assert(!Parse.User.current()); @@ -514,104 +512,104 @@ describe("Parse User", () => { }); }); - 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", + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', }) .then(() => { - user.set("username", "test"); + 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")); + 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) => { + .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.set('username', 'james'); + james.set('password', 'mypass'); james .signUp() .then(() => { const kevin = new Parse.User(); - kevin.set("username", "kevin"); - kevin.set("password", "mypass"); + kevin.set('username', 'kevin'); + kevin.set('password', 'mypass'); return kevin.signUp(); }) .then(() => { const query = new Parse.Query(Parse.User); return query.count(); }) - .then((c) => { + .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) => { - const SuperUser = Parse.Object.extend("User"); + it('handles user subclassing', done => { + const SuperUser = Parse.Object.extend('User'); const user = new SuperUser(); - user.set("username", "bob"); - user.set("password", "welcome"); + user.set('username', 'bob'); + user.set('password', 'welcome'); assert(user instanceof Parse.User); user.signUp().then(() => { done(); }); }); - 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(); }); }); - it("can save anonymous user", async () => { + it('can save anonymous user', async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set("field", "hello"); + user.set('field', 'hello'); await user.save(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get("field")).toBe("hello"); + expect(result.get('field')).toBe('hello'); }); - it("can not recover anonymous user if logged out", async () => { + it('can not recover anonymous user if logged out', async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set("field", "hello"); + user.set('field', 'hello'); await user.save(); await Parse.User.logOut(); @@ -620,75 +618,75 @@ describe("Parse User", () => { try { await query.get(user.id); } catch (error) { - expect(error.message).toBe("Object not found."); + expect(error.message).toBe('Object not found.'); } }); - it("can signUp anonymous user and retain data", async () => { + it('can signUp anonymous user and retain data', async () => { Parse.User.enableUnsafeCurrentUser(); const user = await Parse.AnonymousUtils.logIn(); - user.set("field", "hello world"); + user.set('field', 'hello world'); await user.save(); - expect(user.get("authData").anonymous).toBeDefined(); + expect(user.get('authData').anonymous).toBeDefined(); - user.setUsername("foo"); - user.setPassword("baz"); + user.setUsername('foo'); + user.setPassword('baz'); await user.signUp(); const query = new Parse.Query(Parse.User); const result = await query.get(user.id); - expect(result.get("username")).toBe("foo"); - expect(result.get("authData")).toBeUndefined(); - expect(result.get("field")).toBe("hello world"); - expect(user.get("authData").anonymous).toBeUndefined(); + expect(result.get('username')).toBe('foo'); + expect(result.get('authData')).toBeUndefined(); + expect(result.get('field')).toBe('hello world'); + expect(user.get('authData').anonymous).toBeUndefined(); }); - it("can logIn user without converting anonymous user", async () => { + it('can logIn user without converting anonymous user', async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp("foobaz", "1234"); + await Parse.User.signUp('foobaz', '1234'); const user = await Parse.AnonymousUtils.logIn(); - user.set("field", "hello world"); + user.set('field', 'hello world'); await user.save(); - await Parse.User.logIn("foobaz", "1234"); + await Parse.User.logIn('foobaz', '1234'); const query = new Parse.Query(Parse.User); try { await query.get(user.id); } catch (error) { - expect(error.message).toBe("Object not found."); + expect(error.message).toBe('Object not found.'); } }); - it("anonymous user logIn does not use currentUser sessionToken", async () => { + it('anonymous user logIn does not use currentUser sessionToken', async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp("anon-not", "1234"); + const user1 = await Parse.User.signUp('anon-not', '1234'); const user2 = await Parse.AnonymousUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it("anonymous user link currentUser", async () => { + it('anonymous user link currentUser', async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp("anon-not", "1234"); + const user1 = await Parse.User.signUp('anon-not', '1234'); const user2 = await Parse.AnonymousUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it("anonymous user link does not use currentUser sessionToken", async () => { + it('anonymous user link does not use currentUser sessionToken', async () => { Parse.User.enableUnsafeCurrentUser(); - const user1 = await Parse.User.signUp("anon-not", "1234"); + const user1 = await Parse.User.signUp('anon-not', '1234'); const user2 = new Parse.User(); await Parse.AnonymousUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -696,33 +694,33 @@ describe("Parse User", () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it("facebook logIn does not use currentUser sessionToken", async () => { + it('facebook logIn does not use currentUser sessionToken', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp("facebook-not", "1234"); + const user1 = await Parse.User.signUp('facebook-not', '1234'); const user2 = await Parse.FacebookUtils.logIn(); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it("facebook link currentUser", async () => { + it('facebook link currentUser', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp("facebook-not", "1234"); + const user1 = await Parse.User.signUp('facebook-not', '1234'); const user2 = await Parse.FacebookUtils.link(user1); expect(user1.getSessionToken()).toBeDefined(); expect(user2.getSessionToken()).toBeDefined(); expect(user1.getSessionToken()).toBe(user2.getSessionToken()); }); - it("facebook link does not use currentUser sessionToken", async () => { + it('facebook link does not use currentUser sessionToken', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); - const user1 = await Parse.User.signUp("facebook-not", "1234"); + const user1 = await Parse.User.signUp('facebook-not', '1234'); const user2 = new Parse.User(); await Parse.FacebookUtils.link(user2); expect(user1.getSessionToken()).toBeDefined(); @@ -730,27 +728,27 @@ describe("Parse User", () => { expect(user1.getSessionToken()).not.toBe(user2.getSessionToken()); }); - it("can signUp user with subclass", async () => { + it('can signUp user with subclass', async () => { Parse.User.enableUnsafeCurrentUser(); - const customUser = new CustomUser({ foo: "bar" }); - customUser.setUsername("username"); - customUser.setPassword("password"); + const customUser = new CustomUser({ foo: 'bar' }); + customUser.setUsername('username'); + customUser.setPassword('password'); const user = await customUser.signUp(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get("foo")).toBe("bar"); + expect(user.get('foo')).toBe('bar'); }); - it("can get current with subclass", async () => { + it('can get current with subclass', async () => { Parse.User.enableUnsafeCurrentUser(); - Parse.Object.registerSubclass("_User", CustomUser); + Parse.Object.registerSubclass('_User', CustomUser); - const customUser = new CustomUser({ foo: "bar" }); - customUser.setUsername("username"); - customUser.setPassword("password"); + const customUser = new CustomUser({ foo: 'bar' }); + customUser.setUsername('username'); + customUser.setPassword('password'); await customUser.signUp(); Parse.User._clearCache(); @@ -758,41 +756,41 @@ describe("Parse User", () => { const user = CustomUser.current(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get("foo")).toBe("bar"); + expect(user.get('foo')).toBe('bar'); }); - it("can logIn user with subclass", async () => { + it('can logIn user with subclass', async () => { Parse.User.enableUnsafeCurrentUser(); - await Parse.User.signUp("username", "password"); + await Parse.User.signUp('username', 'password'); - const customUser = new CustomUser({ foo: "bar" }); - customUser.setUsername("username"); - customUser.setPassword("password"); + const customUser = new CustomUser({ foo: 'bar' }); + customUser.setUsername('username'); + customUser.setPassword('password'); const user = await customUser.logIn(); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - expect(user.get("foo")).toBe("bar"); + expect(user.get('foo')).toBe('bar'); }); - it("can signUp / logIn user with subclass static", async () => { + it('can signUp / logIn user with subclass static', async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp("username", "password"); + let user = await CustomUser.signUp('username', 'password'); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); - user = await CustomUser.logIn("username", "password"); + user = await CustomUser.logIn('username', 'password'); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it("can become user with subclass static", async () => { + it('can become user with subclass static', async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp("username", "password"); + let user = await CustomUser.signUp('username', 'password'); const token = user.getSessionToken(); user = await CustomUser.become(token); @@ -800,10 +798,10 @@ describe("Parse User", () => { expect(user.doSomething()).toBe(5); }); - it("can get user (me) with subclass static", async () => { + it('can get user (me) with subclass static', async () => { Parse.User.enableUnsafeCurrentUser(); - let user = await CustomUser.signUp("username", "password"); + let user = await CustomUser.signUp('username', 'password'); const token = user.getSessionToken(); user = await CustomUser.me(token); @@ -811,41 +809,38 @@ describe("Parse User", () => { expect(user.doSomething()).toBe(5); }); - it("can get hydrate user with subclass static", async () => { + it('can get hydrate user with subclass static', async () => { Parse.User.enableUnsafeCurrentUser(); const user = await CustomUser.hydrate({ - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it("can loginWith subclass static", async () => { + it('can loginWith subclass static', async () => { Parse.User.enableUnsafeCurrentUser(); let user = new CustomUser(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); - user = await CustomUser.logInWith( - provider.getAuthType(), - provider.getAuthData() - ); + user = await CustomUser.logInWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); - it("can link without master key", async () => { + it('can link without master key', async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -853,12 +848,12 @@ describe("Parse User", () => { expect(user._isLinked(provider)).toBe(false); }); - it("can link with master key", async () => { + it('can link with master key', async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.save(null, { useMasterKey: true }); await user.linkWith(provider.getAuthType(), provider.getAuthData(), { useMasterKey: true, @@ -868,12 +863,12 @@ describe("Parse User", () => { expect(user._isLinked(provider)).toBe(false); }); - it("can link with session token", async () => { + it('can link with session token', async () => { Parse.User.disableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); expect(user.isCurrent()).toBe(false); @@ -886,10 +881,10 @@ describe("Parse User", () => { expect(user._isLinked(provider)).toBe(false); }); - it("linked account can login with authData", async () => { + it('linked account can login with authData', async () => { const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.save(null, { useMasterKey: true }); await user.linkWith(provider.getAuthType(), provider.getAuthData(), { useMasterKey: true, @@ -897,23 +892,20 @@ describe("Parse User", () => { expect(user._isLinked(provider)).toBe(true); expect(user.authenticated()).toBeFalsy(); Parse.User.enableUnsafeCurrentUser(); - const loggedIn = await Parse.User.logInWith( - provider.getAuthType(), - provider.getAuthData() - ); + const loggedIn = await Parse.User.logInWith(provider.getAuthType(), provider.getAuthData()); expect(loggedIn.authenticated()).toBeTruthy(); }); - it("can linking un-authenticated user without master key", async () => { + it('can linking un-authenticated user without master key', async () => { const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.save(null, { useMasterKey: true }); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user.getSessionToken()).toBeDefined(); }); - it("can link with custom auth", async () => { + it('can link with custom auth', async () => { Parse.User.enableUnsafeCurrentUser(); const provider = { authenticate: () => Promise.resolve(), @@ -922,7 +914,7 @@ describe("Parse User", () => { }, getAuthType() { - return "myAuth"; + return 'myAuth'; }, getAuthData() { @@ -935,8 +927,8 @@ describe("Parse User", () => { }; Parse.User._registerAuthenticationProvider(provider); const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); await user.linkWith(provider.getAuthType(), provider.getAuthData()); expect(user._isLinked(provider)).toBe(true); @@ -944,19 +936,19 @@ describe("Parse User", () => { expect(user._isLinked(provider)).toBe(false); }); - it("can login with facebook", async () => { + it('can login with facebook', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.FacebookUtils.logIn(); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); }); - it("can link user with facebook", async () => { + it('can link user with facebook', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = new Parse.User(); - user.setUsername("Alice"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); @@ -964,7 +956,7 @@ describe("Parse User", () => { expect(Parse.FacebookUtils.isLinked(user)).toBe(false); }); - it("can link anonymous user with facebook", async () => { + it('can link anonymous user with facebook', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.FacebookUtils.init(); const user = await Parse.AnonymousUtils.logIn(); @@ -978,99 +970,96 @@ describe("Parse User", () => { expect(Parse.AnonymousUtils.isLinked(user)).toBe(true); }); - it("can link with twitter", async () => { + it('can link with twitter', async () => { 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"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); - await user.linkWith("twitter", { authData }); + await user.linkWith('twitter', { authData }); - expect(user.get("authData").twitter.id).toBe(authData.id); - expect(user._isLinked("twitter")).toBe(true); + expect(user.get('authData').twitter.id).toBe(authData.id); + expect(user._isLinked('twitter')).toBe(true); - await user._unlinkFrom("twitter"); - expect(user._isLinked("twitter")).toBe(false); + await user._unlinkFrom('twitter'); + expect(user._isLinked('twitter')).toBe(false); }); - it("can link with twitter and facebook", async () => { + it('can link with twitter and facebook', async () => { Parse.User.enableUnsafeCurrentUser(); 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"); - user.setPassword("sekrit"); + user.setUsername('Alice'); + user.setPassword('sekrit'); await user.signUp(); - await user.linkWith("twitter", { authData }); + await user.linkWith('twitter', { authData }); await Parse.FacebookUtils.link(user); expect(Parse.FacebookUtils.isLinked(user)).toBe(true); - expect(user._isLinked("twitter")).toBe(true); + expect(user._isLinked('twitter')).toBe(true); - expect(user.get("authData").twitter.id).toBe(authData.id); - expect(user.get("authData").facebook.id).toBe("test"); + expect(user.get('authData').twitter.id).toBe(authData.id); + expect(user.get('authData').facebook.id).toBe('test'); }); - it("can verify user password via static method", async () => { - await Parse.User.signUp("asd123", "xyz123"); - const res = await Parse.User.verifyPassword("asd123", "xyz123"); - expect(typeof res).toBe("object"); - expect(res.username).toBe("asd123"); + it('can verify user password via static method', async () => { + await Parse.User.signUp('asd123', 'xyz123'); + const res = await Parse.User.verifyPassword('asd123', 'xyz123'); + expect(typeof res).toBe('object'); + expect(res.username).toBe('asd123'); try { - await Parse.User.verifyPassword("asd123", "wrong password"); + await Parse.User.verifyPassword('asd123', 'wrong password'); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe("Invalid username/password."); + expect(error.message).toBe('Invalid username/password.'); } }); - it("can verify user password via instance method", async () => { - const user = await Parse.User.signUp("asd123", "xyz123"); - const res = await user.verifyPassword("xyz123"); - expect(typeof res).toBe("object"); - expect(res.username).toBe("asd123"); + it('can verify user password via instance method', async () => { + const user = await Parse.User.signUp('asd123', 'xyz123'); + const res = await user.verifyPassword('xyz123'); + expect(typeof res).toBe('object'); + expect(res.username).toBe('asd123'); try { - await user.verifyPassword("wrong password"); + await user.verifyPassword('wrong password'); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe("Invalid username/password."); + expect(error.message).toBe('Invalid username/password.'); } }); - it("can encrypt user", async () => { + it('can encrypt user', async () => { Parse.User.enableUnsafeCurrentUser(); Parse.enableEncryptedUser(); - Parse.secret = "My Secret Key"; + Parse.secret = 'My Secret Key'; const user = new Parse.User(); - user.setUsername("usernameENC"); - user.setPassword("passwordENC"); + user.setUsername('usernameENC'); + user.setPassword('passwordENC'); await user.signUp(); - const path = Parse.Storage.generatePath("currentUser"); + const path = Parse.Storage.generatePath('currentUser'); const encryptedUser = Parse.Storage.getItem(path); const crypto = Parse.CoreManager.getCryptoController(); - const decryptedUser = crypto.decrypt( - encryptedUser, - Parse.CoreManager.get("ENCRYPTED_KEY") - ); + const decryptedUser = crypto.decrypt(encryptedUser, Parse.CoreManager.get('ENCRYPTED_KEY')); expect(JSON.parse(decryptedUser).objectId).toBe(user.id); const currentUser = Parse.User.current(); @@ -1079,22 +1068,22 @@ describe("Parse User", () => { const currentUserAsync = await Parse.User.currentAsync(); expect(currentUserAsync).toEqual(user); await Parse.User.logOut(); - Parse.CoreManager.set("ENCRYPTED_USER", false); - Parse.CoreManager.set("ENCRYPTED_KEY", null); + Parse.CoreManager.set('ENCRYPTED_USER', false); + Parse.CoreManager.set('ENCRYPTED_KEY', null); }); - it("fix GHSA-wvh7-5p38-2qfc", async () => { + it('fix GHSA-wvh7-5p38-2qfc', async () => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.setUsername("username"); - user.setPassword("password"); + user.setUsername('username'); + user.setPassword('password'); await user.signUp(); - const path = Parse.Storage.generatePath("currentUser"); + const path = Parse.Storage.generatePath('currentUser'); let userData = Parse.Storage.getItem(path); expect(JSON.parse(userData).password).toBeUndefined(); - user.setPassword("password"); + user.setPassword('password'); await user.save(null, { useMasterKey: true }); userData = Parse.Storage.getItem(path); diff --git a/integration/test/clear.js b/integration/test/clear.js index bbb1aa2e8..2ae35ef2a 100644 --- a/integration/test/clear.js +++ b/integration/test/clear.js @@ -1,4 +1,4 @@ -const Parse = require("../../node"); +const Parse = require('../../node'); /** * Destroys all data in the database @@ -8,5 +8,5 @@ const Parse = require("../../node"); * @returns {Promise} A promise that is resolved when database is deleted. */ module.exports = function (fast = true) { - return Parse._ajax("GET", `http://localhost:1337/clear/${fast}`, ""); + return Parse._ajax('GET', `http://localhost:1337/clear/${fast}`, ''); }; diff --git a/integration/test/helper.js b/integration/test/helper.js index 1663c2948..bade717bf 100644 --- a/integration/test/helper.js +++ b/integration/test/helper.js @@ -1,12 +1,12 @@ -const ParseServer = require("parse-server").ParseServer; +const ParseServer = require('parse-server').ParseServer; jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; -beforeAll((done) => { - const { app } = require("../server"); - const httpServer = require("http").createServer(app); +beforeAll(done => { + const { app } = require('../server'); + const httpServer = require('http').createServer(app); - httpServer.on("error", console.log).listen(1337, () => { - console.log("parse-server running on port 1337."); + httpServer.on('error', console.log).listen(1337, () => { + console.log('parse-server running on port 1337.'); done(); }); ParseServer.createLiveQueryServer(httpServer); diff --git a/integration/test/mockLocalStorage.js b/integration/test/mockLocalStorage.js index ef7cadd13..0728bfb8e 100644 --- a/integration/test/mockLocalStorage.js +++ b/integration/test/mockLocalStorage.js @@ -25,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/src/Analytics.js b/src/Analytics.js index 508aca5bd..348528077 100644 --- a/src/Analytics.js +++ b/src/Analytics.js @@ -9,7 +9,7 @@ * @flow */ -import CoreManager from "./CoreManager"; +import CoreManager from './CoreManager'; /** * Parse.Analytics provides an interface to Parse's logging and analytics @@ -51,22 +51,17 @@ 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 { - name = name || ""; - name = name.replace(/^\s*/, ""); - name = name.replace(/\s*$/, ""); +export function track(name: string, dimensions: { [key: string]: string }): Promise { + name = name || ''; + name = name.replace(/^\s*/, ''); + name = name.replace(/\s*$/, ''); if (name.length === 0) { - throw new TypeError("A name for the custom event must be provided"); + throw new TypeError('A name for the custom event must be provided'); } 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".' - ); + if (typeof key !== 'string' || typeof dimensions[key] !== 'string') { + throw new TypeError('track() dimensions expects keys and values of type "string".'); } } @@ -75,9 +70,9 @@ export function track( const DefaultController = { track(name, dimensions) { - const path = "events/" + name; + const path = 'events/' + name; const RESTController = CoreManager.getRESTController(); - return RESTController.request("POST", path, { dimensions: dimensions }); + return RESTController.request('POST', path, { dimensions: dimensions }); }, }; diff --git a/src/AnonymousUtils.js b/src/AnonymousUtils.js index 3f602aab5..4c8ce6f81 100644 --- a/src/AnonymousUtils.js +++ b/src/AnonymousUtils.js @@ -9,9 +9,9 @@ * @flow-weak */ -import ParseUser from "./ParseUser"; -import type { RequestOptions } from "./RESTController"; -const uuidv4 = require("uuid/v4"); +import ParseUser from './ParseUser'; +import type { RequestOptions } from './RESTController'; +const uuidv4 = require('uuid/v4'); let registered = false; @@ -71,11 +71,7 @@ const AnonymousUtils = { */ logIn(options?: RequestOptions): Promise { const provider = this._getAuthProvider(); - return ParseUser.logInWith( - provider.getAuthType(), - provider.getAuthData(), - options - ); + return ParseUser.logInWith(provider.getAuthType(), provider.getAuthData(), options); }, /** @@ -90,11 +86,7 @@ const AnonymousUtils = { */ link(user: ParseUser, options?: RequestOptions): Promise { const provider = this._getAuthProvider(); - return user.linkWith( - provider.getAuthType(), - provider.getAuthData(), - options - ); + return user.linkWith(provider.getAuthType(), provider.getAuthData(), options); }, _getAuthProvider() { @@ -104,7 +96,7 @@ const AnonymousUtils = { }, getAuthType() { - return "anonymous"; + return 'anonymous'; }, getAuthData() { diff --git a/src/Cloud.js b/src/Cloud.js index 1d015cada..59797e9fd 100644 --- a/src/Cloud.js +++ b/src/Cloud.js @@ -9,13 +9,13 @@ * @flow */ -import CoreManager from "./CoreManager"; -import decode from "./decode"; -import encode from "./encode"; -import ParseError from "./ParseError"; -import ParseQuery from "./ParseQuery"; -import ParseObject from "./ParseObject"; -import type { RequestOptions } from "./RESTController"; +import CoreManager from './CoreManager'; +import decode from './decode'; +import encode from './encode'; +import ParseError from './ParseError'; +import ParseQuery from './ParseQuery'; +import ParseObject from './ParseObject'; +import type { RequestOptions } from './RESTController'; /** * Contains functions for calling and declaring @@ -40,15 +40,11 @@ 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) { - throw new TypeError("Cloud function name must be a string."); + if (typeof name !== 'string' || name.length === 0) { + throw new TypeError('Cloud function name must be a string.'); } const requestOptions = {}; @@ -58,7 +54,7 @@ export function run( if (options.sessionToken) { requestOptions.sessionToken = options.sessionToken; } - if (options.context && typeof options.context === "object") { + if (options.context && typeof options.context === 'object') { requestOptions.context = options.context; } @@ -91,8 +87,8 @@ export function getJobsData(): Promise { * of the job. */ 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."); + if (typeof name !== 'string' || name.length === 0) { + throw new TypeError('Cloud job name must be a string.'); } const requestOptions = { useMasterKey: true, @@ -109,7 +105,7 @@ export function startJob(name: string, data: mixed): Promise { * @returns {Parse.Object} Status of Job. */ export function getJobStatus(jobStatusId: string): Promise { - const query = new ParseQuery("_JobStatus"); + const query = new ParseQuery('_JobStatus'); return query.get(jobStatusId, { useMasterKey: true }); } @@ -119,26 +115,14 @@ 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")) { + if (decoded && decoded.hasOwnProperty('result')) { return Promise.resolve(decoded.result); } return Promise.resolve(undefined); @@ -148,7 +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) { @@ -156,7 +140,7 @@ const DefaultController = { const payload = encode(data, true); - return RESTController.request("POST", "jobs/" + name, payload, options); + return RESTController.request('POST', 'jobs/' + name, payload, options); }, }; diff --git a/src/CoreManager.js b/src/CoreManager.js index 417b8634e..b6a43bfa6 100644 --- a/src/CoreManager.js +++ b/src/CoreManager.js @@ -9,21 +9,16 @@ * @flow */ -import type { - AttributeMap, - ObjectCache, - OpsMap, - State, -} from "./ObjectStateMutations"; -import type ParseFile from "./ParseFile"; -import type { FileSource } from "./ParseFile"; -import type { Op } from "./ParseOp"; -import type ParseObject from "./ParseObject"; -import type { QueryJSON } from "./ParseQuery"; -import type ParseUser from "./ParseUser"; -import type { AuthData } from "./ParseUser"; -import type { PushData } from "./Push"; -import type { RequestOptions, FullOptions } from "./RESTController"; +import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; +import type ParseFile from './ParseFile'; +import type { FileSource } from './ParseFile'; +import type { Op } from './ParseOp'; +import type ParseObject from './ParseObject'; +import type { QueryJSON } from './ParseQuery'; +import type ParseUser from './ParseUser'; +import type { AuthData } from './ParseUser'; +import type { PushData } from './Push'; +import type { RequestOptions, FullOptions } from './RESTController'; type AnalyticsController = { track: (name: string, dimensions: { [key: string]: string }) => Promise, @@ -44,11 +39,7 @@ type CryptoController = { }; type FileController = { saveFile: (name: string, source: FileSource, options: FullOptions) => Promise, - saveBase64: ( - name: string, - source: FileSource, - options: FullOptions - ) => Promise, + saveBase64: (name: string, source: FileSource, options: FullOptions) => Promise, download: (uri: string) => Promise, }; type InstallationController = { @@ -60,14 +51,8 @@ type ObjectController = { forceFetch: boolean, options: RequestOptions ) => Promise, - save: ( - object: ParseObject | Array, - options: RequestOptions - ) => Promise, - destroy: ( - object: ParseObject | Array, - options: RequestOptions - ) => Promise, + save: (object: ParseObject | Array, options: RequestOptions) => Promise, + destroy: (object: ParseObject | Array, options: RequestOptions) => Promise, }; type ObjectStateController = { getState: (obj: any) => ?State, @@ -92,31 +77,12 @@ type PushController = { 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, @@ -124,12 +90,7 @@ type SchemaController = { 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, + send(className: string, method: string, params: any, options: RequestOptions): Promise, }; type SessionController = { getSession: (token: RequestOptions) => Promise, @@ -166,11 +127,7 @@ type UserController = { setCurrentUser: (user: ParseUser) => Promise, currentUser: () => ?ParseUser, currentUserAsync: () => Promise, - signUp: ( - user: ParseUser, - attrs: AttributeMap, - options: RequestOptions - ) => Promise, + signUp: (user: ParseUser, attrs: AttributeMap, options: RequestOptions) => Promise, logIn: (user: ParseUser, options: RequestOptions) => Promise, become: (options: RequestOptions) => Promise, hydrate: (userJSON: AttributeMap) => Promise, @@ -178,17 +135,10 @@ type UserController = { me: (options: RequestOptions) => Promise, requestPasswordReset: (email: string, options: RequestOptions) => Promise, updateUserOnDisk: (user: ParseUser) => Promise, - upgradeToRevocableSession: ( - user: ParseUser, - options: RequestOptions - ) => Promise, + upgradeToRevocableSession: (user: ParseUser, options: RequestOptions) => Promise, linkWith: (user: ParseUser, authData: AuthData) => Promise, removeUserFromDisk: () => Promise, - verifyPassword: ( - username: string, - password: string, - options: RequestOptions - ) => Promise, + verifyPassword: (username: string, password: string, options: RequestOptions) => Promise, requestEmailVerification: (email: string, options: RequestOptions) => Promise, }; type HooksController = { @@ -229,19 +179,19 @@ type Config = { const config: Config & { [key: string]: mixed } = { // Defaults IS_NODE: - typeof process !== "undefined" && + typeof process !== 'undefined' && !!process.versions && !!process.versions.node && !process.versions.electron, REQUEST_ATTEMPT_LIMIT: 5, REQUEST_BATCH_SIZE: 20, REQUEST_HEADERS: {}, - SERVER_URL: "https://api.parse.com/1", + SERVER_URL: 'https://api.parse.com/1', SERVER_AUTH_TYPE: null, SERVER_AUTH_TOKEN: null, LIVEQUERY_SERVER_URL: null, ENCRYPTED_KEY: null, - VERSION: "js" + require("../package.json").version, + VERSION: 'js' + require('../package.json').version, APPLICATION_ID: null, JAVASCRIPT_KEY: null, MASTER_KEY: null, @@ -253,8 +203,8 @@ const config: Config & { [key: string]: mixed } = { }; function requireMethods(name: string, methods: Array, controller: any) { - methods.forEach((func) => { - if (typeof controller[func] !== "function") { + methods.forEach(func => { + if (typeof controller[func] !== 'function') { throw new Error(`${name} must implement ${func}()`); } }); @@ -265,7 +215,7 @@ module.exports = { if (config.hasOwnProperty(key)) { return config[key]; } - throw new Error("Configuration key not found: " + key); + throw new Error('Configuration key not found: ' + key); }, set: function (key: string, value: any): void { @@ -275,278 +225,252 @@ module.exports = { /* Specialized Controller Setters/Getters */ setAnalyticsController(controller: AnalyticsController) { - requireMethods("AnalyticsController", ["track"], controller); - config["AnalyticsController"] = controller; + requireMethods('AnalyticsController', ['track'], controller); + config['AnalyticsController'] = controller; }, getAnalyticsController(): AnalyticsController { - return config["AnalyticsController"]; + return config['AnalyticsController']; }, setCloudController(controller: CloudController) { - requireMethods( - "CloudController", - ["run", "getJobsData", "startJob"], - controller - ); - config["CloudController"] = controller; + requireMethods('CloudController', ['run', 'getJobsData', 'startJob'], controller); + config['CloudController'] = controller; }, getCloudController(): CloudController { - return config["CloudController"]; + return config['CloudController']; }, setConfigController(controller: ConfigController) { - requireMethods("ConfigController", ["current", "get", "save"], controller); - config["ConfigController"] = controller; + requireMethods('ConfigController', ['current', 'get', 'save'], controller); + config['ConfigController'] = controller; }, getConfigController(): ConfigController { - return config["ConfigController"]; + return config['ConfigController']; }, setCryptoController(controller: CryptoController) { - requireMethods("CryptoController", ["encrypt", "decrypt"], controller); - config["CryptoController"] = controller; + requireMethods('CryptoController', ['encrypt', 'decrypt'], controller); + config['CryptoController'] = controller; }, getCryptoController(): CryptoController { - return config["CryptoController"]; + return config['CryptoController']; }, setFileController(controller: FileController) { - requireMethods("FileController", ["saveFile", "saveBase64"], controller); - config["FileController"] = controller; + requireMethods('FileController', ['saveFile', 'saveBase64'], controller); + config['FileController'] = controller; }, getFileController(): FileController { - return config["FileController"]; + return config['FileController']; }, setInstallationController(controller: InstallationController) { - requireMethods( - "InstallationController", - ["currentInstallationId"], - controller - ); - config["InstallationController"] = controller; + requireMethods('InstallationController', ['currentInstallationId'], controller); + config['InstallationController'] = controller; }, getInstallationController(): InstallationController { - return config["InstallationController"]; + return config['InstallationController']; }, setObjectController(controller: ObjectController) { - requireMethods( - "ObjectController", - ["save", "fetch", "destroy"], - controller - ); - config["ObjectController"] = controller; + requireMethods('ObjectController', ['save', 'fetch', 'destroy'], controller); + config['ObjectController'] = controller; }, getObjectController(): ObjectController { - return config["ObjectController"]; + return config['ObjectController']; }, setObjectStateController(controller: ObjectStateController) { requireMethods( - "ObjectStateController", + 'ObjectStateController', [ - "getState", - "initializeState", - "removeState", - "getServerData", - "setServerData", - "getPendingOps", - "setPendingOp", - "pushPendingState", - "popPendingState", - "mergeFirstPendingState", - "getObjectCache", - "estimateAttribute", - "estimateAttributes", - "commitServerChanges", - "enqueueTask", - "clearAllState", + 'getState', + 'initializeState', + 'removeState', + 'getServerData', + 'setServerData', + 'getPendingOps', + 'setPendingOp', + 'pushPendingState', + 'popPendingState', + 'mergeFirstPendingState', + 'getObjectCache', + 'estimateAttribute', + 'estimateAttributes', + 'commitServerChanges', + 'enqueueTask', + 'clearAllState', ], controller ); - config["ObjectStateController"] = controller; + config['ObjectStateController'] = controller; }, getObjectStateController(): ObjectStateController { - return config["ObjectStateController"]; + return config['ObjectStateController']; }, setPushController(controller: PushController) { - requireMethods("PushController", ["send"], controller); - config["PushController"] = controller; + requireMethods('PushController', ['send'], controller); + config['PushController'] = controller; }, getPushController(): PushController { - return config["PushController"]; + return config['PushController']; }, setQueryController(controller: QueryController) { - requireMethods("QueryController", ["find", "aggregate"], controller); - config["QueryController"] = controller; + requireMethods('QueryController', ['find', 'aggregate'], controller); + config['QueryController'] = controller; }, getQueryController(): QueryController { - return config["QueryController"]; + return config['QueryController']; }, setRESTController(controller: RESTController) { - requireMethods("RESTController", ["request", "ajax"], controller); - config["RESTController"] = controller; + requireMethods('RESTController', ['request', 'ajax'], controller); + config['RESTController'] = controller; }, getRESTController(): RESTController { - return config["RESTController"]; + return config['RESTController']; }, setSchemaController(controller: SchemaController) { requireMethods( - "SchemaController", - ["get", "create", "update", "delete", "send", "purge"], + 'SchemaController', + ['get', 'create', 'update', 'delete', 'send', 'purge'], controller ); - config["SchemaController"] = controller; + config['SchemaController'] = controller; }, getSchemaController(): SchemaController { - return config["SchemaController"]; + return config['SchemaController']; }, setSessionController(controller: SessionController) { - requireMethods("SessionController", ["getSession"], controller); - config["SessionController"] = controller; + requireMethods('SessionController', ['getSession'], controller); + config['SessionController'] = controller; }, getSessionController(): SessionController { - return config["SessionController"]; + return config['SessionController']; }, setStorageController(controller: StorageController) { if (controller.async) { requireMethods( - "An async StorageController", - ["getItemAsync", "setItemAsync", "removeItemAsync", "getAllKeysAsync"], + 'An async StorageController', + ['getItemAsync', 'setItemAsync', 'removeItemAsync', 'getAllKeysAsync'], controller ); } else { requireMethods( - "A synchronous StorageController", - ["getItem", "setItem", "removeItem", "getAllKeys"], + 'A synchronous StorageController', + ['getItem', 'setItem', 'removeItem', 'getAllKeys'], controller ); } - config["StorageController"] = controller; + config['StorageController'] = controller; }, setLocalDatastoreController(controller: LocalDatastoreController) { requireMethods( - "LocalDatastoreController", - [ - "pinWithName", - "fromPinWithName", - "unPinWithName", - "getAllContents", - "clear", - ], + 'LocalDatastoreController', + ['pinWithName', 'fromPinWithName', 'unPinWithName', 'getAllContents', 'clear'], controller ); - config["LocalDatastoreController"] = controller; + config['LocalDatastoreController'] = controller; }, getLocalDatastoreController(): LocalDatastoreController { - return config["LocalDatastoreController"]; + return config['LocalDatastoreController']; }, setLocalDatastore(store: any) { - config["LocalDatastore"] = store; + config['LocalDatastore'] = store; }, getLocalDatastore() { - return config["LocalDatastore"]; + return config['LocalDatastore']; }, getStorageController(): StorageController { - return config["StorageController"]; + return config['StorageController']; }, setAsyncStorage(storage: any) { - config["AsyncStorage"] = storage; + config['AsyncStorage'] = storage; }, getAsyncStorage() { - return config["AsyncStorage"]; + return config['AsyncStorage']; }, setWebSocketController(controller: WebSocketController) { - config["WebSocketController"] = controller; + config['WebSocketController'] = controller; }, getWebSocketController(): WebSocketController { - return config["WebSocketController"]; + return config['WebSocketController']; }, setUserController(controller: UserController) { requireMethods( - "UserController", + 'UserController', [ - "setCurrentUser", - "currentUser", - "currentUserAsync", - "signUp", - "logIn", - "become", - "logOut", - "me", - "requestPasswordReset", - "upgradeToRevocableSession", - "requestEmailVerification", - "verifyPassword", - "linkWith", + 'setCurrentUser', + 'currentUser', + 'currentUserAsync', + 'signUp', + 'logIn', + 'become', + 'logOut', + 'me', + 'requestPasswordReset', + 'upgradeToRevocableSession', + 'requestEmailVerification', + 'verifyPassword', + 'linkWith', ], controller ); - config["UserController"] = controller; + config['UserController'] = controller; }, getUserController(): UserController { - return config["UserController"]; + return config['UserController']; }, setLiveQueryController(controller: any) { requireMethods( - "LiveQueryController", - [ - "setDefaultLiveQueryClient", - "getDefaultLiveQueryClient", - "_clearCachedDefaultClient", - ], + 'LiveQueryController', + ['setDefaultLiveQueryClient', 'getDefaultLiveQueryClient', '_clearCachedDefaultClient'], controller ); - config["LiveQueryController"] = controller; + config['LiveQueryController'] = controller; }, getLiveQueryController(): any { - return config["LiveQueryController"]; + return config['LiveQueryController']; }, setHooksController(controller: HooksController) { - requireMethods( - "HooksController", - ["create", "get", "update", "remove"], - controller - ); - config["HooksController"] = controller; + requireMethods('HooksController', ['create', 'get', 'update', 'remove'], controller); + config['HooksController'] = controller; }, getHooksController(): HooksController { - return config["HooksController"]; + return config['HooksController']; }, }; diff --git a/src/CryptoController.js b/src/CryptoController.js index 173c820b3..49b7fc725 100644 --- a/src/CryptoController.js +++ b/src/CryptoController.js @@ -1,13 +1,13 @@ let AES; let ENC; -if (process.env.PARSE_BUILD === "react-native") { - const CryptoJS = require("react-native-crypto-js"); +if (process.env.PARSE_BUILD === 'react-native') { + const CryptoJS = require('react-native-crypto-js'); AES = CryptoJS.AES; ENC = CryptoJS.enc.Utf8; } else { - AES = require("crypto-js/aes"); - ENC = require("crypto-js/enc-utf8"); + AES = require('crypto-js/aes'); + ENC = require('crypto-js/enc-utf8'); } const CryptoController = { diff --git a/src/EventEmitter.js b/src/EventEmitter.js index c9351f9be..47d6a1c85 100644 --- a/src/EventEmitter.js +++ b/src/EventEmitter.js @@ -9,10 +9,10 @@ * This is a simple wrapper to unify EventEmitter implementations across platforms. */ -if (process.env.PARSE_BUILD === "react-native") { - const EventEmitter = require("../../../react-native/Libraries/vendor/emitter/EventEmitter"); +if (process.env.PARSE_BUILD === 'react-native') { + const EventEmitter = require('../../../react-native/Libraries/vendor/emitter/EventEmitter'); EventEmitter.prototype.on = EventEmitter.prototype.addListener; module.exports = EventEmitter; } else { - module.exports = require("events").EventEmitter; + module.exports = require('events').EventEmitter; } diff --git a/src/FacebookUtils.js b/src/FacebookUtils.js index 06111f00b..b8ec0fe27 100644 --- a/src/FacebookUtils.js +++ b/src/FacebookUtils.js @@ -9,18 +9,18 @@ * @flow-weak */ /* global FB */ -import ParseUser from "./ParseUser"; +import ParseUser from './ParseUser'; let initialized = false; let requestedPermissions; let initOptions; const provider = { authenticate(options) { - if (typeof FB === "undefined") { - options.error(this, "Facebook SDK not found."); + if (typeof FB === 'undefined') { + options.error(this, 'Facebook SDK not found.'); } FB.login( - (response) => { + response => { if (response.authResponse) { if (options.success) { options.success(this, { @@ -69,7 +69,7 @@ const provider = { }, getAuthType() { - return "facebook"; + return 'facebook'; }, deauthenticate() { @@ -104,10 +104,8 @@ const FacebookUtils = { * explicitly if this behavior is required by your application. */ init(options) { - if (typeof FB === "undefined") { - throw new Error( - "The Facebook JavaScript SDK must be loaded before calling init." - ); + if (typeof FB === 'undefined') { + throw new Error('The Facebook JavaScript SDK must be loaded before calling init.'); } initOptions = {}; if (options) { @@ -115,14 +113,14 @@ const FacebookUtils = { initOptions[key] = options[key]; } } - if (initOptions.status && typeof console !== "undefined") { + 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." + ' 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; @@ -142,7 +140,7 @@ const FacebookUtils = { * linked to Facebook. */ isLinked(user) { - return user._isLinked("facebook"); + return user._isLinked('facebook'); }, /** @@ -170,17 +168,15 @@ const FacebookUtils = { * @returns {Promise} */ logIn(permissions, options) { - if (!permissions || typeof permissions === "string") { + 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); + return ParseUser.logInWith('facebook', options); } const authData = { authData: permissions }; - return ParseUser.logInWith("facebook", authData, options); + return ParseUser.logInWith('facebook', authData, options); }, /** @@ -210,17 +206,15 @@ const FacebookUtils = { * @returns {Promise} */ link(user, permissions, options) { - if (!permissions || typeof permissions === "string") { + 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); + return user.linkWith('facebook', options); } const authData = { authData: permissions }; - return user.linkWith("facebook", authData, options); + return user.linkWith('facebook', authData, options); }, /** @@ -236,11 +230,9 @@ const FacebookUtils = { */ 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); + return user._unlinkFrom('facebook', options); }, // Used for testing purposes diff --git a/src/InstallationController.js b/src/InstallationController.js index 9ad01aaf4..c99697e4b 100644 --- a/src/InstallationController.js +++ b/src/InstallationController.js @@ -9,18 +9,18 @@ * @flow */ -import Storage from "./Storage"; -const uuidv4 = require("uuid/v4"); +import Storage from './Storage'; +const uuidv4 = require('uuid/v4'); let iidCache = null; const InstallationController = { currentInstallationId(): Promise { - if (typeof iidCache === "string") { + if (typeof iidCache === 'string') { return Promise.resolve(iidCache); } - const path = Storage.generatePath("installationId"); - return Storage.getItemAsync(path).then((iid) => { + const path = Storage.generatePath('installationId'); + return Storage.getItemAsync(path).then(iid => { if (!iid) { iid = uuidv4(); return Storage.setItemAsync(path, iid).then(() => { diff --git a/src/LiveQueryClient.js b/src/LiveQueryClient.js index 88f1bf90d..e9a4391ae 100644 --- a/src/LiveQueryClient.js +++ b/src/LiveQueryClient.js @@ -9,63 +9,63 @@ */ /* global WebSocket */ -import CoreManager from "./CoreManager"; -import EventEmitter from "./EventEmitter"; -import ParseObject from "./ParseObject"; -import LiveQuerySubscription from "./LiveQuerySubscription"; -import { resolvingPromise } from "./promiseUtils"; +import CoreManager from './CoreManager'; +import EventEmitter from './EventEmitter'; +import ParseObject from './ParseObject'; +import LiveQuerySubscription from './LiveQuerySubscription'; +import { resolvingPromise } from './promiseUtils'; // The LiveQuery client inner state const CLIENT_STATE = { - INITIALIZED: "initialized", - CONNECTING: "connecting", - CONNECTED: "connected", - CLOSED: "closed", - RECONNECTING: "reconnecting", - DISCONNECTED: "disconnected", + INITIALIZED: 'initialized', + CONNECTING: 'connecting', + CONNECTED: 'connected', + CLOSED: 'closed', + RECONNECTING: 'reconnecting', + DISCONNECTED: 'disconnected', }; // The event type the LiveQuery client should sent to server const OP_TYPES = { - CONNECT: "connect", - SUBSCRIBE: "subscribe", - UNSUBSCRIBE: "unsubscribe", - ERROR: "error", + CONNECT: 'connect', + SUBSCRIBE: 'subscribe', + UNSUBSCRIBE: 'unsubscribe', + ERROR: 'error', }; // The event we get back from LiveQuery server const OP_EVENTS = { - CONNECTED: "connected", - SUBSCRIBED: "subscribed", - UNSUBSCRIBED: "unsubscribed", - ERROR: "error", - CREATE: "create", - UPDATE: "update", - ENTER: "enter", - LEAVE: "leave", - DELETE: "delete", + CONNECTED: 'connected', + SUBSCRIBED: 'subscribed', + UNSUBSCRIBED: 'unsubscribed', + ERROR: 'error', + CREATE: 'create', + UPDATE: 'update', + ENTER: 'enter', + LEAVE: 'leave', + DELETE: 'delete', }; // The event the LiveQuery client should emit const CLIENT_EMMITER_TYPES = { - CLOSE: "close", - ERROR: "error", - OPEN: "open", + CLOSE: 'close', + ERROR: 'error', + OPEN: 'open', }; // The event the LiveQuery subscription should emit const SUBSCRIPTION_EMMITER_TYPES = { - OPEN: "open", - CLOSE: "close", - ERROR: "error", - CREATE: "create", - UPDATE: "update", - ENTER: "enter", - LEAVE: "leave", - DELETE: "delete", + OPEN: 'open', + CLOSE: 'close', + ERROR: 'error', + CREATE: 'create', + UPDATE: 'update', + ENTER: 'enter', + LEAVE: 'leave', + DELETE: 'delete', }; -const generateInterval = (k) => { +const generateInterval = k => { return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000; }; @@ -148,9 +148,9 @@ class LiveQueryClient extends EventEmitter { }) { super(); - if (!serverURL || serverURL.indexOf("ws") !== 0) { + if (!serverURL || serverURL.indexOf('ws') !== 0) { throw new Error( - "You need to set a proper Parse LiveQuery server url before using LiveQueryClient" + 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' ); } @@ -171,14 +171,11 @@ class LiveQueryClient extends EventEmitter { // adding listener so process does not crash // best practice is for developer to register their own listener - this.on("error", () => {}); + this.on('error', () => {}); } shouldOpen(): any { - return ( - this.state === CLIENT_STATE.INITIALIZED || - this.state === CLIENT_STATE.DISCONNECTED - ); + return this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED; } /** @@ -202,7 +199,7 @@ class LiveQueryClient extends EventEmitter { const className = query.className; const queryJSON = query.toJSON(); const where = queryJSON.where; - const fields = queryJSON.keys ? queryJSON.keys.split(",") : undefined; + const fields = queryJSON.keys ? queryJSON.keys.split(',') : undefined; const subscribeRequest = { op: OP_TYPES.SUBSCRIBE, requestId: this.requestId, @@ -217,11 +214,7 @@ class LiveQueryClient extends EventEmitter { subscribeRequest.sessionToken = sessionToken; } - const subscription = new LiveQuerySubscription( - this.requestId, - query, - sessionToken - ); + const subscription = new LiveQuerySubscription(this.requestId, query, sessionToken); this.subscriptions.set(this.requestId, subscription); this.requestId += 1; this.connectPromise.then(() => { @@ -259,10 +252,7 @@ class LiveQueryClient extends EventEmitter { open() { const WebSocketImplementation = CoreManager.getWebSocketController(); if (!WebSocketImplementation) { - this.emit( - CLIENT_EMMITER_TYPES.ERROR, - "Can not find WebSocket implementation" - ); + this.emit(CLIENT_EMMITER_TYPES.ERROR, 'Can not find WebSocket implementation'); return; } @@ -277,7 +267,7 @@ class LiveQueryClient extends EventEmitter { this._handleWebSocketOpen(); }; - this.socket.onmessage = (event) => { + this.socket.onmessage = event => { this._handleWebSocketMessage(event); }; @@ -285,7 +275,7 @@ class LiveQueryClient extends EventEmitter { this._handleWebSocketClose(); }; - this.socket.onerror = (error) => { + this.socket.onerror = error => { this._handleWebSocketError(error); }; } @@ -295,7 +285,7 @@ class LiveQueryClient extends EventEmitter { const query = subscription.query; const queryJSON = query.toJSON(); const where = queryJSON.where; - const fields = queryJSON.keys ? queryJSON.keys.split(",") : undefined; + const fields = queryJSON.keys ? queryJSON.keys.split(',') : undefined; const className = query.className; const sessionToken = subscription.sessionToken; const subscribeRequest = { @@ -324,10 +314,7 @@ class LiveQueryClient extends EventEmitter { * */ close() { - if ( - this.state === CLIENT_STATE.INITIALIZED || - this.state === CLIENT_STATE.DISCONNECTED - ) { + if (this.state === CLIENT_STATE.INITIALIZED || this.state === CLIENT_STATE.DISCONNECTED) { return; } this.state = CLIENT_STATE.DISCONNECTED; @@ -367,7 +354,7 @@ class LiveQueryClient extends EventEmitter { _handleWebSocketMessage(event: any) { let data = event.data; - if (typeof data === "string") { + if (typeof data === 'string') { data = JSON.parse(data); } let subscription = null; @@ -392,26 +379,19 @@ class LiveQueryClient extends EventEmitter { if (subscription) { subscription.subscribed = true; subscription.subscribePromise.resolve(); - setTimeout( - () => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), - 200 - ); + setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), 200); } break; case OP_EVENTS.ERROR: if (data.requestId) { if (subscription) { subscription.subscribePromise.resolve(); - setTimeout( - () => - subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), - 200 - ); + setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), 200); } } else { this.emit(CLIENT_EMMITER_TYPES.ERROR, data.error); } - if (data.error === "Additional properties not allowed") { + if (data.error === 'Additional properties not allowed') { this.additionalProperties = false; } if (data.reconnect) { @@ -505,17 +485,15 @@ class LiveQueryClient extends EventEmitter { } } -if (process.env.PARSE_BUILD === "node") { - CoreManager.setWebSocketController(require("ws")); -} else if (process.env.PARSE_BUILD === "browser") { +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 + 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") { +} else if (process.env.PARSE_BUILD === 'weapp') { + CoreManager.setWebSocketController(require('./Socket.weapp')); +} else if (process.env.PARSE_BUILD === 'react-native') { CoreManager.setWebSocketController(WebSocket); } diff --git a/src/LiveQuerySubscription.js b/src/LiveQuerySubscription.js index af53ae77a..0c5cf1b3d 100644 --- a/src/LiveQuerySubscription.js +++ b/src/LiveQuerySubscription.js @@ -8,9 +8,9 @@ * */ -import EventEmitter from "./EventEmitter"; -import CoreManager from "./CoreManager"; -import { resolvingPromise } from "./promiseUtils"; +import EventEmitter from './EventEmitter'; +import CoreManager from './CoreManager'; +import { resolvingPromise } from './promiseUtils'; /** * Creates a new LiveQuery Subscription. @@ -113,7 +113,7 @@ class Subscription extends EventEmitter { // adding listener so process does not crash // best practice is for developer to register their own listener - this.on("error", () => {}); + this.on('error', () => {}); } /** @@ -124,9 +124,9 @@ class Subscription extends EventEmitter { unsubscribe(): Promise { return CoreManager.getLiveQueryController() .getDefaultLiveQueryClient() - .then((liveQueryClient) => { + .then(liveQueryClient => { liveQueryClient.unsubscribe(this); - this.emit("close"); + this.emit('close'); }); } } diff --git a/src/LocalDatastore.js b/src/LocalDatastore.js index 6497487ff..7250c0375 100644 --- a/src/LocalDatastore.js +++ b/src/LocalDatastore.js @@ -9,11 +9,11 @@ * @flow */ -import CoreManager from "./CoreManager"; +import CoreManager from './CoreManager'; -import type ParseObject from "./ParseObject"; -import ParseQuery from "./ParseQuery"; -import { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX } from "./LocalDatastoreUtils"; +import type ParseObject from './ParseObject'; +import ParseQuery from './ParseQuery'; +import { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX } from './LocalDatastoreUtils'; /** * Provides a local datastore which can be used to store and retrieve Parse.Object.
@@ -72,10 +72,7 @@ const LocalDatastore = { // Pin the object and children recursively // Saves the object and children key to Pin Name - async _handlePinAllWithName( - name: string, - objects: Array - ): Promise { + async _handlePinAllWithName(name: string, objects: Array): Promise { const pinName = this.getPinName(name); const toPinPromises = []; const objectKeys = []; @@ -113,7 +110,7 @@ const LocalDatastore = { objectKeys = [...new Set(objectKeys)]; let pinned = localDatastore[pinName] || []; - pinned = pinned.filter((item) => !objectKeys.includes(item)); + pinned = pinned.filter(item => !objectKeys.includes(item)); if (pinned.length == 0) { promises.push(this.unPinWithName(pinName)); delete localDatastore[pinName]; @@ -144,7 +141,7 @@ const LocalDatastore = { const encountered = {}; const json = object._toFullJSON(undefined, true); for (const key in json) { - if (json[key] && json[key].__type && json[key].__type === "Object") { + if (json[key] && json[key].__type && json[key].__type === 'Object') { this._traverse(json[key], encountered); } } @@ -166,7 +163,7 @@ const LocalDatastore = { if (!object[key]) { json = object; } - if (json.__type && json.__type === "Object") { + if (json.__type && json.__type === 'Object') { this._traverse(json, encountered); } } @@ -189,10 +186,10 @@ 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); + return objects.filter(object => object != null); }, // Replaces object pointers with pinned pointers @@ -219,7 +216,7 @@ const LocalDatastore = { const subTreeRoot = meta[nodeId]; for (const field in subTreeRoot) { const value = subTreeRoot[field]; - if (value.__type && value.__type === "Object") { + if (value.__type && value.__type === 'Object') { const key = this.getKeyForObject(value); if (LDS[key] && LDS[key].length > 0) { const pointer = LDS[key][0]; @@ -268,7 +265,7 @@ const LocalDatastore = { if (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX)) { let pinned = localDatastore[key] || []; if (pinned.includes(objectKey)) { - pinned = pinned.filter((item) => item !== objectKey); + pinned = pinned.filter(item => item !== objectKey); if (pinned.length == 0) { promises.push(this.unPinWithName(key)); delete localDatastore[key]; @@ -294,17 +291,14 @@ 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) { if (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX)) { let pinned = localDatastore[key] || []; if (pinned.includes(localKey)) { - pinned = pinned.filter((item) => item !== localKey); + pinned = pinned.filter(item => item !== localKey); pinned.push(objectKey); promises.push(this.pinWithName(key, pinned)); localDatastore[key] = pinned; @@ -343,14 +337,14 @@ 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") { - className = "_User"; - objectId = key.split("_")[4]; + if (key.split('_').length === 5 && key.split('_')[3] === 'User') { + className = '_User'; + objectId = key.split('_')[4]; } - if (objectId.startsWith("local")) { + if (objectId.startsWith('local')) { continue; } if (!(className in pointersHash)) { @@ -358,28 +352,28 @@ const LocalDatastore = { } pointersHash[className].add(objectId); } - const queryPromises = Object.keys(pointersHash).map((className) => { + const queryPromises = Object.keys(pointersHash).map(className => { const objectIds = Array.from(pointersHash[className]); const query = new ParseQuery(className); query.limit(objectIds.length); if (objectIds.length === 1) { - query.equalTo("objectId", objectIds[0]); + query.equalTo('objectId', objectIds[0]); } else { - query.containedIn("objectId", objectIds); + query.containedIn('objectId', objectIds); } return query.find(); }); 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) { - console.error("Error syncing LocalDatastore: ", error); + console.error('Error syncing LocalDatastore: ', error); this.isSyncing = false; } }, @@ -398,7 +392,7 @@ const LocalDatastore = { checkIfEnabled() { if (!this.isEnabled) { - console.error("Parse.enableLocalDatastore() must be called first"); + console.error('Parse.enableLocalDatastore() must be called first'); } return this.isEnabled; }, @@ -406,13 +400,9 @@ const LocalDatastore = { module.exports = LocalDatastore; -if (process.env.PARSE_BUILD === "react-native") { - CoreManager.setLocalDatastoreController( - require("./LocalDatastoreController.react-native") - ); +if (process.env.PARSE_BUILD === 'react-native') { + CoreManager.setLocalDatastoreController(require('./LocalDatastoreController.react-native')); } else { - CoreManager.setLocalDatastoreController( - require("./LocalDatastoreController") - ); + CoreManager.setLocalDatastoreController(require('./LocalDatastoreController')); } CoreManager.setLocalDatastore(LocalDatastore); diff --git a/src/LocalDatastoreController.js b/src/LocalDatastoreController.js index 7f0448a42..dd8b6dffe 100644 --- a/src/LocalDatastoreController.js +++ b/src/LocalDatastoreController.js @@ -8,8 +8,8 @@ * * @flow */ -import { isLocalDatastoreKey } from "./LocalDatastoreUtils"; -import Storage from "./Storage"; +import { isLocalDatastoreKey } from './LocalDatastoreUtils'; +import Storage from './Storage'; const LocalDatastoreController = { async fromPinWithName(name: string): Array { @@ -39,7 +39,7 @@ const LocalDatastoreController = { try { LDS[key] = JSON.parse(value); } catch (error) { - console.error("Error getAllContents: ", error); + console.error('Error getAllContents: ', error); } } return LDS; diff --git a/src/LocalDatastoreController.react-native.js b/src/LocalDatastoreController.react-native.js index 85658b2e9..6b6a77135 100644 --- a/src/LocalDatastoreController.react-native.js +++ b/src/LocalDatastoreController.react-native.js @@ -10,8 +10,8 @@ * @private */ -import { isLocalDatastoreKey } from "./LocalDatastoreUtils"; -const RNStorage = require("./StorageController.react-native"); +import { isLocalDatastoreKey } from './LocalDatastoreUtils'; +const RNStorage = require('./StorageController.react-native'); const LocalDatastoreController = { async fromPinWithName(name: string): Promise> { @@ -51,10 +51,10 @@ const LocalDatastoreController = { try { results = await RNStorage.multiGet(batch); } catch (error) { - console.error("Error getAllContents: ", error); + 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,8 @@ 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) ); }, }; diff --git a/src/LocalDatastoreUtils.js b/src/LocalDatastoreUtils.js index 2c4b5c9a1..d6922284f 100644 --- a/src/LocalDatastoreUtils.js +++ b/src/LocalDatastoreUtils.js @@ -10,16 +10,14 @@ * @private */ -const DEFAULT_PIN = "_default"; -const PIN_PREFIX = "parsePin_"; -const OBJECT_PREFIX = "Parse_LDS_"; +const DEFAULT_PIN = '_default'; +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)) + (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX) || key.startsWith(OBJECT_PREFIX)) ); } diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index e476b0f88..f9911847e 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -9,14 +9,14 @@ * @flow */ -import encode from "./encode"; -import ParseFile from "./ParseFile"; -import ParseObject from "./ParseObject"; -import ParseRelation from "./ParseRelation"; -import TaskQueue from "./TaskQueue"; -import { RelationOp } from "./ParseOp"; +import encode from './encode'; +import ParseFile from './ParseFile'; +import ParseObject from './ParseObject'; +import ParseRelation from './ParseRelation'; +import TaskQueue from './TaskQueue'; +import { RelationOp } from './ParseOp'; -import type { Op } from "./ParseOp"; +import type { Op } from './ParseOp'; export type AttributeMap = { [attr: string]: any }; export type OpsMap = { [attr: string]: Op }; @@ -40,12 +40,9 @@ export function defaultState(): State { }; } -export function setServerData( - serverData: AttributeMap, - attributes: AttributeMap -) { +export function setServerData(serverData: AttributeMap, attributes: AttributeMap) { for (const attr in attributes) { - if (typeof attributes[attr] !== "undefined") { + if (typeof attributes[attr] !== 'undefined') { serverData[attr] = attributes[attr]; } else { delete serverData[attr]; @@ -101,11 +98,7 @@ export function estimateAttribute( 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); @@ -137,9 +130,9 @@ export function estimateAttributes( ); } } else { - if (attr.includes(".")) { + if (attr.includes('.')) { // convert a.b.c into { a: { b: { c: value } } } - const fields = attr.split("."); + const fields = attr.split('.'); const first = fields[0]; const last = fields[fields.length - 1]; data[first] = { ...serverData[first] }; @@ -167,7 +160,7 @@ export function commitServerChanges( serverData[attr] = val; if ( val && - typeof val === "object" && + typeof val === 'object' && !(val instanceof ParseObject) && !(val instanceof ParseFile) && !(val instanceof ParseRelation) diff --git a/src/OfflineQuery.js b/src/OfflineQuery.js index c6ad584db..a53ad7daa 100644 --- a/src/OfflineQuery.js +++ b/src/OfflineQuery.js @@ -1,8 +1,8 @@ -const equalObjects = require("./equals").default; -const decode = require("./decode").default; -const ParseError = require("./ParseError").default; -const ParsePolygon = require("./ParsePolygon").default; -const ParseGeoPoint = require("./ParseGeoPoint").default; +const equalObjects = require('./equals').default; +const decode = require('./decode').default; +const ParseError = require('./ParseError').default; +const ParsePolygon = require('./ParsePolygon').default; +const ParseGeoPoint = require('./ParseGeoPoint').default; /** * contains -- Determines if an object is contained in a list with special handling for Parse pointers. @@ -13,20 +13,13 @@ const ParseGeoPoint = require("./ParseGeoPoint").default; * @returns {boolean} */ function contains(haystack, needle) { - if ( - needle && - needle.__type && - (needle.__type === "Pointer" || needle.__type === "Object") - ) { + if (needle && needle.__type && (needle.__type === 'Pointer' || needle.__type === 'Object')) { for (const i in haystack) { const ptr = haystack[i]; - if (typeof ptr === "string" && ptr === needle.objectId) { + if (typeof ptr === 'string' && ptr === needle.objectId) { return true; } - if ( - ptr.className === needle.className && - ptr.objectId === needle.objectId - ) { + if (ptr.className === needle.className && ptr.objectId === needle.objectId) { return true; } } @@ -102,11 +95,11 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { if (constraints === null) { return false; } - if (key.indexOf(".") >= 0) { + if (key.indexOf('.') >= 0) { // Key references a subobject - const keyComponents = key.split("."); + const keyComponents = key.split('.'); const subObjectKey = keyComponents[0]; - const keyRemainder = keyComponents.slice(1).join("."); + const keyRemainder = keyComponents.slice(1).join('.'); return matchesKeyConstraints( className, object[subObjectKey] || {}, @@ -116,7 +109,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { ); } let i; - if (key === "$or") { + if (key === '$or') { for (i = 0; i < constraints.length; i++) { if (matchesQuery(className, object, objects, constraints[i])) { return true; @@ -124,7 +117,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - if (key === "$and") { + if (key === '$and') { for (i = 0; i < constraints.length; i++) { if (!matchesQuery(className, object, objects, constraints[i])) { return false; @@ -132,7 +125,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - if (key === "$nor") { + if (key === '$nor') { for (i = 0; i < constraints.length; i++) { if (matchesQuery(className, object, objects, constraints[i])) { return false; @@ -140,7 +133,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - if (key === "$relatedTo") { + if (key === '$relatedTo') { // Bail! We can't handle relational queries locally return false; } @@ -148,7 +141,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { throw new ParseError(ParseError.INVALID_KEY_NAME, `Invalid Key: ${key}`); } // Equality (or Array contains) cases - if (typeof constraints !== "object") { + if (typeof constraints !== 'object') { if (Array.isArray(object[key])) { return object[key].indexOf(constraints) > -1; } @@ -156,20 +149,16 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } let compareTo; if (constraints.__type) { - if (constraints.__type === "Pointer") { + if (constraints.__type === 'Pointer') { return equalObjectsGeneric(object[key], constraints, function (obj, ptr) { return ( - typeof obj !== "undefined" && + typeof obj !== 'undefined' && ptr.className === obj.className && ptr.objectId === obj.objectId ); }); } - return equalObjectsGeneric( - decode(object[key]), - decode(constraints), - equalObjects - ); + return equalObjectsGeneric(decode(object[key]), decode(constraints), equalObjects); } // More complex cases for (const condition in constraints) { @@ -179,96 +168,93 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } // Compare Date Object or Date String if ( - toString.call(compareTo) === "[object Date]" || - (typeof compareTo === "string" && - new Date(compareTo) !== "Invalid Date" && + toString.call(compareTo) === '[object Date]' || + (typeof compareTo === 'string' && + new Date(compareTo) !== 'Invalid Date' && !isNaN(new Date(compareTo))) ) { object[key] = new Date(object[key].iso ? object[key].iso : object[key]); } switch (condition) { - case "$lt": + case '$lt': if (object[key] >= compareTo) { return false; } break; - case "$lte": + case '$lte': if (object[key] > compareTo) { return false; } break; - case "$gt": + case '$gt': if (object[key] <= compareTo) { return false; } break; - case "$gte": + case '$gte': if (object[key] < compareTo) { return false; } break; - case "$ne": + case '$ne': if (equalObjects(object[key], compareTo)) { return false; } break; - case "$in": + case '$in': if (!contains(compareTo, object[key])) { return false; } break; - case "$nin": + case '$nin': if (contains(compareTo, object[key])) { return false; } break; - case "$all": + case '$all': for (i = 0; i < compareTo.length; i++) { if (object[key].indexOf(compareTo[i]) < 0) { return false; } } break; - case "$exists": { - const propertyExists = typeof object[key] !== "undefined"; - const existenceIsRequired = constraints["$exists"]; - if (typeof constraints["$exists"] !== "boolean") { + case '$exists': { + const propertyExists = typeof object[key] !== 'undefined'; + const existenceIsRequired = constraints['$exists']; + if (typeof constraints['$exists'] !== 'boolean') { // The SDK will never submit a non-boolean for $exists, but if someone // tries to submit a non-boolean for $exits outside the SDKs, just ignore it. break; } - if ( - (!propertyExists && existenceIsRequired) || - (propertyExists && !existenceIsRequired) - ) { + if ((!propertyExists && existenceIsRequired) || (propertyExists && !existenceIsRequired)) { return false; } break; } - case "$regex": { - if (typeof compareTo === "object") { + case '$regex': { + if (typeof compareTo === 'object') { return compareTo.test(object[key]); } // JS doesn't support perl-style escaping - let expString = ""; + let expString = ''; let escapeEnd = -2; - let escapeStart = compareTo.indexOf("\\Q"); + let escapeStart = compareTo.indexOf('\\Q'); while (escapeStart > -1) { // Add the unescaped portion expString += compareTo.substring(escapeEnd + 2, escapeStart); - escapeEnd = compareTo.indexOf("\\E", escapeStart); + escapeEnd = compareTo.indexOf('\\E', escapeStart); if (escapeEnd > -1) { expString += compareTo .substring(escapeStart + 2, escapeEnd) - .replace(/\\\\\\\\E/g, "\\E") - .replace(/\W/g, "\\$&"); + .replace(/\\\\\\\\E/g, '\\E') + .replace(/\W/g, '\\$&'); } - escapeStart = compareTo.indexOf("\\Q", escapeEnd); + escapeStart = compareTo.indexOf('\\Q', escapeEnd); } expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2)); - let modifiers = constraints.$options || ""; - modifiers = modifiers.replace("x", "").replace("s", ""); + let modifiers = constraints.$options || ''; + 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])) { @@ -276,7 +262,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } break; } - case "$nearSphere": { + case '$nearSphere': { if (!compareTo || !object[key]) { return false; } @@ -284,16 +270,13 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { const max = constraints.$maxDistance || Infinity; return distance <= max; } - case "$within": { + case '$within': { if (!compareTo || !object[key]) { return false; } const southWest = compareTo.$box[0]; const northEast = compareTo.$box[1]; - if ( - southWest.latitude > northEast.latitude || - southWest.longitude > northEast.longitude - ) { + if (southWest.latitude > northEast.latitude || southWest.longitude > northEast.longitude) { // Invalid box, crosses the date line return false; } @@ -304,22 +287,17 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { object[key].longitude < northEast.longitude ); } - case "$options": + case '$options': // Not a query type, but a way to add options to $regex. Ignore and // avoid the default break; - case "$maxDistance": + case '$maxDistance': // Not a query type, but a way to add a cap to $nearSphere. Ignore and // avoid the default break; - case "$select": { + case '$select': { const subQueryObjects = objects.filter((obj, index, arr) => { - return matchesQuery( - compareTo.query.className, - obj, - arr, - compareTo.query.where - ); + return matchesQuery(compareTo.query.className, obj, arr, compareTo.query.where); }); for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); @@ -327,14 +305,9 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - case "$dontSelect": { + case '$dontSelect': { const subQueryObjects = objects.filter((obj, index, arr) => { - return matchesQuery( - compareTo.query.className, - obj, - arr, - compareTo.query.where - ); + return matchesQuery(compareTo.query.className, obj, arr, compareTo.query.where); }); for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); @@ -342,7 +315,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - case "$inQuery": { + case '$inQuery': { const subQueryObjects = objects.filter((obj, index, arr) => { return matchesQuery(compareTo.className, obj, arr, compareTo.where); }); @@ -358,7 +331,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return false; } - case "$notInQuery": { + case '$notInQuery': { const subQueryObjects = objects.filter((obj, index, arr) => { return matchesQuery(compareTo.className, obj, arr, compareTo.where); }); @@ -374,7 +347,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - case "$containedBy": { + case '$containedBy': { for (const value of object[key]) { if (!contains(compareTo, value)) { return false; @@ -382,15 +355,12 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { } return true; } - case "$geoWithin": { - const points = compareTo.$polygon.map((geoPoint) => [ - geoPoint.latitude, - geoPoint.longitude, - ]); + case '$geoWithin': { + const points = compareTo.$polygon.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]); const polygon = new ParsePolygon(points); return polygon.containsPoint(object[key]); } - case "$geoIntersects": { + case '$geoIntersects': { const polygon = new ParsePolygon(object[key].coordinates); const point = new ParseGeoPoint(compareTo.$point); return polygon.containsPoint(point); @@ -409,21 +379,21 @@ function validateQuery(query: any) { 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", + '$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) => { + Object.keys(q).forEach(key => { if (q && q[key] && q[key].$regex) { - if (typeof q[key].$options === "string") { + if (typeof q[key].$options === 'string') { if (!q[key].$options.match(/^[imxs]+$/)) { throw new ParseError( ParseError.INVALID_QUERY, @@ -432,14 +402,8 @@ function validateQuery(query: any) { } } } - if ( - specialQuerykeys.indexOf(key) < 0 && - !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/) - ) { - throw new ParseError( - ParseError.INVALID_KEY_NAME, - `Invalid key name: ${key}` - ); + if (specialQuerykeys.indexOf(key) < 0 && !key.match(/^[a-zA-Z][a-zA-Z0-9_\.]*$/)) { + throw new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: ${key}`); } }); } diff --git a/src/Parse.js b/src/Parse.js index 431c2dd3f..a627da859 100644 --- a/src/Parse.js +++ b/src/Parse.js @@ -7,13 +7,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import decode from "./decode"; -import encode from "./encode"; -import CoreManager from "./CoreManager"; -import CryptoController from "./CryptoController"; -import InstallationController from "./InstallationController"; -import * as ParseOp from "./ParseOp"; -import RESTController from "./RESTController"; +import decode from './decode'; +import encode from './encode'; +import CoreManager from './CoreManager'; +import CryptoController from './CryptoController'; +import InstallationController from './InstallationController'; +import * as ParseOp from './ParseOp'; +import RESTController from './RESTController'; /** * Contains all Parse API classes and functions. @@ -34,8 +34,8 @@ const Parse = { */ initialize(applicationId: string, javaScriptKey: string) { if ( - process.env.PARSE_BUILD === "browser" && - CoreManager.get("IS_NODE") && + process.env.PARSE_BUILD === 'browser' && + CoreManager.get('IS_NODE') && !process.env.SERVER_RENDERING ) { /* eslint-disable no-console */ @@ -49,10 +49,10 @@ const Parse = { }, _initialize(applicationId: string, javaScriptKey: string, masterKey: string) { - CoreManager.set("APPLICATION_ID", applicationId); - CoreManager.set("JAVASCRIPT_KEY", javaScriptKey); - CoreManager.set("MASTER_KEY", masterKey); - CoreManager.set("USE_MASTER_KEY", false); + CoreManager.set('APPLICATION_ID', applicationId); + CoreManager.set('JAVASCRIPT_KEY', javaScriptKey); + CoreManager.set('MASTER_KEY', masterKey); + CoreManager.set('USE_MASTER_KEY', false); }, /** @@ -83,10 +83,10 @@ const Parse = { * @static */ set applicationId(value) { - CoreManager.set("APPLICATION_ID", value); + CoreManager.set('APPLICATION_ID', value); }, get applicationId() { - return CoreManager.get("APPLICATION_ID"); + return CoreManager.get('APPLICATION_ID'); }, /** @@ -94,10 +94,10 @@ const Parse = { * @static */ set javaScriptKey(value) { - CoreManager.set("JAVASCRIPT_KEY", value); + CoreManager.set('JAVASCRIPT_KEY', value); }, get javaScriptKey() { - return CoreManager.get("JAVASCRIPT_KEY"); + return CoreManager.get('JAVASCRIPT_KEY'); }, /** @@ -105,10 +105,10 @@ const Parse = { * @static */ set masterKey(value) { - CoreManager.set("MASTER_KEY", value); + CoreManager.set('MASTER_KEY', value); }, get masterKey() { - return CoreManager.get("MASTER_KEY"); + return CoreManager.get('MASTER_KEY'); }, /** @@ -116,10 +116,10 @@ const Parse = { * @static */ set serverURL(value) { - CoreManager.set("SERVER_URL", value); + CoreManager.set('SERVER_URL', value); }, get serverURL() { - return CoreManager.get("SERVER_URL"); + return CoreManager.get('SERVER_URL'); }, /** @@ -127,10 +127,10 @@ const Parse = { * @static */ set serverAuthToken(value) { - CoreManager.set("SERVER_AUTH_TOKEN", value); + CoreManager.set('SERVER_AUTH_TOKEN', value); }, get serverAuthToken() { - return CoreManager.get("SERVER_AUTH_TOKEN"); + return CoreManager.get('SERVER_AUTH_TOKEN'); }, /** @@ -138,10 +138,10 @@ const Parse = { * @static */ set serverAuthType(value) { - CoreManager.set("SERVER_AUTH_TYPE", value); + CoreManager.set('SERVER_AUTH_TYPE', value); }, get serverAuthType() { - return CoreManager.get("SERVER_AUTH_TYPE"); + return CoreManager.get('SERVER_AUTH_TYPE'); }, /** @@ -149,10 +149,10 @@ const Parse = { * @static */ set liveQueryServerURL(value) { - CoreManager.set("LIVEQUERY_SERVER_URL", value); + CoreManager.set('LIVEQUERY_SERVER_URL', value); }, get liveQueryServerURL() { - return CoreManager.get("LIVEQUERY_SERVER_URL"); + return CoreManager.get('LIVEQUERY_SERVER_URL'); }, /** @@ -160,10 +160,10 @@ const Parse = { * @static */ set encryptedUser(value) { - CoreManager.set("ENCRYPTED_USER", value); + CoreManager.set('ENCRYPTED_USER', value); }, get encryptedUser() { - return CoreManager.get("ENCRYPTED_USER"); + return CoreManager.get('ENCRYPTED_USER'); }, /** @@ -171,10 +171,10 @@ const Parse = { * @static */ set secret(value) { - CoreManager.set("ENCRYPTED_KEY", value); + CoreManager.set('ENCRYPTED_KEY', value); }, get secret() { - return CoreManager.get("ENCRYPTED_KEY"); + return CoreManager.get('ENCRYPTED_KEY'); }, /** @@ -182,27 +182,27 @@ const Parse = { * @static */ set idempotency(value) { - CoreManager.set("IDEMPOTENCY", value); + CoreManager.set('IDEMPOTENCY', value); }, get idempotency() { - return CoreManager.get("IDEMPOTENCY"); + return CoreManager.get('IDEMPOTENCY'); }, }; -Parse.ACL = require("./ParseACL").default; -Parse.Analytics = require("./Analytics"); -Parse.AnonymousUtils = require("./AnonymousUtils").default; -Parse.Cloud = require("./Cloud"); -Parse.CoreManager = require("./CoreManager"); -Parse.Config = require("./ParseConfig").default; -Parse.Error = require("./ParseError").default; -Parse.FacebookUtils = require("./FacebookUtils").default; -Parse.File = require("./ParseFile").default; -Parse.GeoPoint = require("./ParseGeoPoint").default; -Parse.Polygon = require("./ParsePolygon").default; -Parse.Installation = require("./ParseInstallation").default; -Parse.LocalDatastore = require("./LocalDatastore"); -Parse.Object = require("./ParseObject").default; +Parse.ACL = require('./ParseACL').default; +Parse.Analytics = require('./Analytics'); +Parse.AnonymousUtils = require('./AnonymousUtils').default; +Parse.Cloud = require('./Cloud'); +Parse.CoreManager = require('./CoreManager'); +Parse.Config = require('./ParseConfig').default; +Parse.Error = require('./ParseError').default; +Parse.FacebookUtils = require('./FacebookUtils').default; +Parse.File = require('./ParseFile').default; +Parse.GeoPoint = require('./ParseGeoPoint').default; +Parse.Polygon = require('./ParsePolygon').default; +Parse.Installation = require('./ParseInstallation').default; +Parse.LocalDatastore = require('./LocalDatastore'); +Parse.Object = require('./ParseObject').default; Parse.Op = { Set: ParseOp.SetOp, Unset: ParseOp.UnsetOp, @@ -212,16 +212,16 @@ Parse.Op = { AddUnique: ParseOp.AddUniqueOp, Relation: ParseOp.RelationOp, }; -Parse.Push = require("./Push"); -Parse.Query = require("./ParseQuery").default; -Parse.Relation = require("./ParseRelation").default; -Parse.Role = require("./ParseRole").default; -Parse.Schema = require("./ParseSchema").default; -Parse.Session = require("./ParseSession").default; -Parse.Storage = require("./Storage"); -Parse.User = require("./ParseUser").default; -Parse.LiveQuery = require("./ParseLiveQuery").default; -Parse.LiveQueryClient = require("./LiveQueryClient").default; +Parse.Push = require('./Push'); +Parse.Query = require('./ParseQuery').default; +Parse.Relation = require('./ParseRelation').default; +Parse.Role = require('./ParseRole').default; +Parse.Schema = require('./ParseSchema').default; +Parse.Session = require('./ParseSession').default; +Parse.Storage = require('./Storage'); +Parse.User = require('./ParseUser').default; +Parse.LiveQuery = require('./ParseLiveQuery').default; +Parse.LiveQueryClient = require('./LiveQueryClient').default; Parse._request = function (...args) { return CoreManager.getRESTController().request.apply(null, args); @@ -269,7 +269,7 @@ Parse.isLocalDatastoreEnabled = function () { */ Parse.dumpLocalDatastore = function () { if (!Parse.LocalDatastore.isEnabled) { - console.log("Parse.enableLocalDatastore() must be called first"); // eslint-disable-line no-console + console.log('Parse.enableLocalDatastore() must be called first'); // eslint-disable-line no-console return Promise.resolve({}); } else { return Parse.LocalDatastore._getAllContents(); @@ -300,13 +300,13 @@ CoreManager.setCryptoController(CryptoController); CoreManager.setInstallationController(InstallationController); CoreManager.setRESTController(RESTController); -if (process.env.PARSE_BUILD === "node") { +if (process.env.PARSE_BUILD === 'node') { Parse.initialize = Parse._initialize; Parse.Cloud = Parse.Cloud || {}; Parse.Cloud.useMasterKey = function () { - CoreManager.set("USE_MASTER_KEY", true); + CoreManager.set('USE_MASTER_KEY', true); }; - Parse.Hooks = require("./ParseHooks"); + Parse.Hooks = require('./ParseHooks'); } // For legacy requires, of the form `var Parse = require('parse').Parse` diff --git a/src/ParseACL.js b/src/ParseACL.js index 00e38ee70..398f6607f 100644 --- a/src/ParseACL.js +++ b/src/ParseACL.js @@ -9,13 +9,13 @@ * @flow */ -import ParseRole from "./ParseRole"; -import ParseUser from "./ParseUser"; +import ParseRole from './ParseRole'; +import ParseUser from './ParseUser'; type PermissionsMap = { [permission: string]: boolean }; type ByIdMap = { [userId: string]: PermissionsMap }; -const PUBLIC_KEY = "*"; +const PUBLIC_KEY = '*'; /** * Creates a new ACL. @@ -39,7 +39,7 @@ class ParseACL { */ constructor(arg1: ParseUser | ByIdMap) { this.permissionsById = {}; - if (arg1 && typeof arg1 === "object") { + if (arg1 && typeof arg1 === 'object') { if (arg1 instanceof ParseUser) { this.setReadAccess(arg1, true); this.setWriteAccess(arg1, true); @@ -49,24 +49,18 @@ class ParseACL { this.permissionsById[userId] = {}; 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." - ); + if (permission !== 'read' && permission !== 'write') { + 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." - ); + if (typeof allowed !== 'boolean') { + 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 ()?" - ); + } else if (typeof arg1 === 'function') { + throw new TypeError('ParseACL constructed with a function. Did you forget ()?'); } } @@ -112,25 +106,21 @@ class ParseACL { return true; } - _setAccess( - accessType: string, - userId: ParseUser | ParseRole | string, - allowed: boolean - ) { + _setAccess(accessType: string, userId: ParseUser | ParseRole | string, allowed: boolean) { if (userId instanceof ParseUser) { userId = userId.id; } else if (userId instanceof ParseRole) { const name = userId.getName(); if (!name) { - throw new TypeError("Role must have a name"); + throw new TypeError('Role must have a name'); } - userId = "role:" + name; + userId = 'role:' + name; } - if (typeof userId !== "string") { - throw new TypeError("userId must be a string."); + if (typeof userId !== 'string') { + throw new TypeError('userId must be a string.'); } - if (typeof allowed !== "boolean") { - throw new TypeError("allowed must be either true or false."); + if (typeof allowed !== 'boolean') { + throw new TypeError('allowed must be either true or false.'); } let permissions = this.permissionsById[userId]; if (!permissions) { @@ -153,21 +143,18 @@ 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) { - throw new Error("Cannot get access for a ParseUser without an ID"); + throw new Error('Cannot get access for a ParseUser without an ID'); } } else if (userId instanceof ParseRole) { const name = userId.getName(); if (!name) { - throw new TypeError("Role must have a name"); + throw new TypeError('Role must have a name'); } - userId = "role:" + name; + userId = 'role:' + name; } const permissions = this.permissionsById[userId]; if (!permissions) { @@ -183,7 +170,7 @@ class ParseACL { * @param {boolean} allowed Whether that user should have read access. */ setReadAccess(userId: ParseUser | ParseRole | string, allowed: boolean) { - this._setAccess("read", userId, allowed); + this._setAccess('read', userId, allowed); } /** @@ -196,7 +183,7 @@ class ParseACL { * @returns {boolean} */ getReadAccess(userId: ParseUser | ParseRole | string): boolean { - return this._getAccess("read", userId); + return this._getAccess('read', userId); } /** @@ -206,7 +193,7 @@ class ParseACL { * @param {boolean} allowed Whether that user should have write access. */ setWriteAccess(userId: ParseUser | ParseRole | string, allowed: boolean) { - this._setAccess("write", userId, allowed); + this._setAccess('write', userId, allowed); } /** @@ -219,7 +206,7 @@ class ParseACL { * @returns {boolean} */ getWriteAccess(userId: ParseUser | ParseRole | string): boolean { - return this._getAccess("write", userId); + return this._getAccess('write', userId); } /** @@ -272,10 +259,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== "string") { - throw new TypeError("role must be a ParseRole or a String"); + if (typeof role !== 'string') { + throw new TypeError('role must be a ParseRole or a String'); } - return this.getReadAccess("role:" + role); + return this.getReadAccess('role:' + role); } /** @@ -292,10 +279,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== "string") { - throw new TypeError("role must be a ParseRole or a String"); + if (typeof role !== 'string') { + throw new TypeError('role must be a ParseRole or a String'); } - return this.getWriteAccess("role:" + role); + return this.getWriteAccess('role:' + role); } /** @@ -311,10 +298,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== "string") { - throw new TypeError("role must be a ParseRole or a String"); + if (typeof role !== 'string') { + throw new TypeError('role must be a ParseRole or a String'); } - this.setReadAccess("role:" + role, allowed); + this.setReadAccess('role:' + role, allowed); } /** @@ -330,10 +317,10 @@ class ParseACL { // Normalize to the String name role = role.getName(); } - if (typeof role !== "string") { - throw new TypeError("role must be a ParseRole or a String"); + if (typeof role !== 'string') { + throw new TypeError('role must be a ParseRole or a String'); } - this.setWriteAccess("role:" + role, allowed); + this.setWriteAccess('role:' + role, allowed); } } diff --git a/src/ParseConfig.js b/src/ParseConfig.js index 9d0e0a9e3..de77a8097 100644 --- a/src/ParseConfig.js +++ b/src/ParseConfig.js @@ -9,14 +9,14 @@ * @flow */ -import CoreManager from "./CoreManager"; -import decode from "./decode"; -import encode from "./encode"; -import escape from "./escape"; -import ParseError from "./ParseError"; -import Storage from "./Storage"; +import CoreManager from './CoreManager'; +import decode from './decode'; +import encode from './encode'; +import escape from './escape'; +import ParseError from './ParseError'; +import Storage from './Storage'; -import type { RequestOptions } from "./RESTController"; +import type { RequestOptions } from './RESTController'; /** * Parse.Config is a local representation of configuration data that @@ -56,7 +56,7 @@ class ParseConfig { return html; } const val = this.attributes[attr]; - let escaped = ""; + let escaped = ''; if (val != null) { escaped = escape(val.toString()); } @@ -107,17 +107,14 @@ class ParseConfig { * @returns {Promise} A promise that is resolved with a newly-created * configuration object or with the current with the update. */ - static save( - attrs: { [key: string]: any }, - masterKeyOnlyFlags: { [key: string]: any } - ) { + 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) => { + error => { return Promise.reject(error); } ); @@ -135,12 +132,12 @@ class ParseConfig { let currentConfig = null; -const CURRENT_CONFIG_KEY = "currentConfig"; +const CURRENT_CONFIG_KEY = 'currentConfig'; function decodePayload(data) { try { const json = JSON.parse(data); - if (json && typeof json === "object") { + if (json && typeof json === 'object') { return decode(json); } } catch (e) { @@ -169,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) { @@ -184,53 +181,45 @@ const DefaultController = { get(options: RequestOptions = {}) { const RESTController = CoreManager.getRESTController(); - return RESTController.request("GET", "config", {}, options).then( - (response) => { - if (!response || !response.params) { - const error = new ParseError( - ParseError.INVALID_JSON, - "Config JSON response invalid." - ); - return Promise.reject(error); - } + return RESTController.request('GET', 'config', {}, options).then(response => { + if (!response || !response.params) { + const error = new ParseError(ParseError.INVALID_JSON, 'Config JSON response invalid.'); + return Promise.reject(error); + } - const config = new ParseConfig(); - config.attributes = {}; - for (const attr in response.params) { - config.attributes[attr] = decode(response.params[attr]); - } - currentConfig = config; - return Storage.setItemAsync( - Storage.generatePath(CURRENT_CONFIG_KEY), - JSON.stringify(response.params) - ).then(() => { - return config; - }); + const config = new ParseConfig(); + config.attributes = {}; + for (const attr in response.params) { + config.attributes[attr] = decode(response.params[attr]); } - ); + currentConfig = config; + return Storage.setItemAsync( + Storage.generatePath(CURRENT_CONFIG_KEY), + JSON.stringify(response.params) + ).then(() => { + return config; + }); + }); }, - save( - attrs: { [key: string]: any }, - masterKeyOnlyFlags: { [key: string]: any } - ) { + 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]); } return RESTController.request( - "PUT", - "config", + 'PUT', + 'config', { params: encodedAttrs, masterKeyOnly: masterKeyOnlyFlags }, { useMasterKey: true } - ).then((response) => { + ).then(response => { if (response && response.result) { return Promise.resolve(); } else { const error = new ParseError( ParseError.INTERNAL_SERVER_ERROR, - "Error occured updating Config." + 'Error occured updating Config.' ); return Promise.reject(error); } diff --git a/src/ParseError.js b/src/ParseError.js index 59e876344..79d5358ff 100644 --- a/src/ParseError.js +++ b/src/ParseError.js @@ -20,14 +20,14 @@ class ParseError extends Error { constructor(code, message) { super(message); this.code = code; - Object.defineProperty(this, "message", { + Object.defineProperty(this, 'message', { enumerable: true, value: message, }); } toString() { - return "ParseError: " + this.code + " " + this.message; + return 'ParseError: ' + this.code + ' ' + this.message; } } diff --git a/src/ParseFile.js b/src/ParseFile.js index 0b8fbb695..d4ff9b520 100644 --- a/src/ParseFile.js +++ b/src/ParseFile.js @@ -9,17 +9,17 @@ * @flow */ /* global XMLHttpRequest, Blob */ -import CoreManager from "./CoreManager"; -import type { FullOptions } from "./RESTController"; +import CoreManager from './CoreManager'; +import type { FullOptions } from './RESTController'; -const ParseError = require("./ParseError").default; +const ParseError = require('./ParseError').default; let XHR = null; -if (typeof XMLHttpRequest !== "undefined") { +if (typeof XMLHttpRequest !== 'undefined') { XHR = XMLHttpRequest; } -if (process.env.PARSE_BUILD === "weapp") { - XHR = require("./Xhr.weapp"); +if (process.env.PARSE_BUILD === 'weapp') { + XHR = require('./Xhr.weapp'); } type Base64 = { base64: string }; @@ -27,17 +27,17 @@ type Uri = { uri: string }; type FileData = Array | Base64 | Blob | Uri; export type FileSource = | { - format: "file", + format: 'file', file: Blob, type: string, } | { - format: "base64", + format: 'base64', base64: string, type: string, } | { - format: "uri", + format: 'uri', uri: string, type: string, }; @@ -55,12 +55,12 @@ function b64Digit(number: number): string { return String.fromCharCode(48 + (number - 52)); } if (number === 62) { - return "+"; + return '+'; } if (number === 63) { - return "/"; + return '/'; } - throw new TypeError("Tried to encode large digit " + number + " in base64."); + throw new TypeError('Tried to encode large digit ' + number + ' in base64.'); } /** @@ -109,14 +109,8 @@ class ParseFile { * @param metadata {Object} Optional key value pairs to be stored with file object * @param tags {Object} Optional key value pairs to be stored with file object */ - constructor( - name: string, - data?: FileData, - type?: string, - metadata?: Object, - tags?: Object - ) { - const specifiedType = type || ""; + constructor(name: string, data?: FileData, type?: string, metadata?: Object, tags?: Object) { + const specifiedType = type || ''; this._name = name; this._metadata = metadata || {}; @@ -126,49 +120,45 @@ class ParseFile { if (Array.isArray(data)) { this._data = ParseFile.encodeBase64(data); this._source = { - format: "base64", + format: 'base64', base64: this._data, type: specifiedType, }; - } else if (typeof Blob !== "undefined" && data instanceof Blob) { + } else if (typeof Blob !== 'undefined' && data instanceof Blob) { this._source = { - format: "file", + format: 'file', file: data, type: specifiedType, }; - } else if ( - data && - typeof data.uri === "string" && - data.uri !== undefined - ) { + } else if (data && typeof data.uri === 'string' && data.uri !== undefined) { this._source = { - format: "uri", + format: 'uri', uri: data.uri, type: specifiedType, }; - } else if (data && typeof data.base64 === "string") { + } else if (data && typeof data.base64 === 'string') { const base64 = data.base64; - const commaIndex = base64.indexOf(","); + const commaIndex = base64.indexOf(','); if (commaIndex !== -1) { const matches = dataUriRegexp.exec(base64.slice(0, commaIndex + 1)); // if data URI with type and charset, there will be 4 matches. this._data = base64.slice(commaIndex + 1); this._source = { - format: "base64", + format: 'base64', base64: this._data, type: matches[1], }; } else { this._data = base64; this._source = { - format: "base64", + format: 'base64', base64: base64, type: specifiedType, }; } } else { - throw new TypeError("Cannot create a Parse.File with that data."); + throw new TypeError('Cannot create a Parse.File with that data.'); } } } @@ -185,10 +175,10 @@ class ParseFile { return this._data; } if (!this._url) { - throw new Error("Cannot retrieve data for unsaved 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); @@ -220,7 +210,7 @@ class ParseFile { return; } if (options.forceSecure) { - return this._url.replace(/^http:\/\//i, "https://"); + return this._url.replace(/^http:\/\//i, 'https://'); } else { return this._url; } @@ -269,31 +259,29 @@ 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._name = res.name; - this._url = res.url; - this._data = null; - this._requestTask = null; - return this; - }); - } else if (this._source.format === "uri") { + if (this._source.format === 'file') { + this._previousSave = controller.saveFile(this._name, this._source, options).then(res => { + this._name = res.name; + this._url = res.url; + this._data = null; + this._requestTask = null; + return this; + }); + } else if (this._source.format === 'uri') { this._previousSave = controller .download(this._source.uri, options) - .then((result) => { + .then(result => { if (!(result && result.base64)) { return {}; } const newSource = { - format: "base64", + format: 'base64', base64: result.base64, type: result.contentType, }; @@ -301,21 +289,19 @@ class ParseFile { this._requestTask = null; return controller.saveBase64(this._name, newSource, options); }) - .then((res) => { + .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._name = res.name; - this._url = res.url; - this._requestTask = null; - return this; - }); + this._previousSave = controller.saveBase64(this._name, this._source, options).then(res => { + this._name = res.name; + this._url = res.url; + this._requestTask = null; + return this; + }); } } if (this._previousSave) { @@ -327,7 +313,7 @@ class ParseFile { * Aborts the request if it has already been sent. */ cancel() { - if (this._requestTask && typeof this._requestTask.abort === "function") { + if (this._requestTask && typeof this._requestTask.abort === 'function') { this._requestTask.abort(); } this._requestTask = null; @@ -341,10 +327,7 @@ class ParseFile { */ destroy() { if (!this._name) { - throw new ParseError( - ParseError.FILE_DELETE_UNNAMED_ERROR, - "Cannot delete an unnamed file." - ); + throw new ParseError(ParseError.FILE_DELETE_UNNAMED_ERROR, 'Cannot delete an unnamed file.'); } const controller = CoreManager.getFileController(); return controller.deleteFile(this._name).then(() => { @@ -356,7 +339,7 @@ class ParseFile { toJSON(): { name: ?string, url: ?string } { return { - __type: "File", + __type: 'File', name: this._name, url: this._url, }; @@ -371,7 +354,7 @@ class ParseFile { other instanceof ParseFile && this.name() === other.name() && this.url() === other.url() && - typeof this.url() !== "undefined" + typeof this.url() !== 'undefined' ); } @@ -381,8 +364,8 @@ class ParseFile { * @param {object} metadata Key value pairs to be stored with file object */ setMetadata(metadata: any) { - if (metadata && typeof metadata === "object") { - Object.keys(metadata).forEach((key) => { + if (metadata && typeof metadata === 'object') { + Object.keys(metadata).forEach(key => { this.addMetadata(key, metadata[key]); }); } @@ -395,7 +378,7 @@ class ParseFile { * @param {*} value metadata */ addMetadata(key: string, value: any) { - if (typeof key === "string") { + if (typeof key === 'string') { this._metadata[key] = value; } } @@ -406,8 +389,8 @@ class ParseFile { * @param {object} tags Key value pairs to be stored with file object */ setTags(tags: any) { - if (tags && typeof tags === "object") { - Object.keys(tags).forEach((key) => { + if (tags && typeof tags === 'object') { + Object.keys(tags).forEach(key => { this.addTag(key, tags[key]); }); } @@ -420,14 +403,14 @@ class ParseFile { * @param {*} value tag */ addTag(key: string, value: string) { - if (typeof key === "string") { + if (typeof key === 'string') { this._tags[key] = value; } } static fromJSON(obj): ParseFile { - if (obj.__type !== "File") { - throw new TypeError("JSON object does not represent a ParseFile"); + if (obj.__type !== 'File') { + throw new TypeError('JSON object does not represent a ParseFile'); } const file = new ParseFile(obj.name); file._url = obj.url; @@ -448,52 +431,44 @@ class ParseFile { 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) : "=", - ].join(""); + has2 ? b64Digit(((b2 << 2) & 0x3c) | ((b3 >> 6) & 0x03)) : '=', + has3 ? b64Digit(b3 & 0x3f) : '=', + ].join(''); } - return chunks.join(""); + return chunks.join(''); } } const DefaultController = { - 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."); + 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.'); } const base64Data = await new Promise((res, rej) => { // eslint-disable-next-line no-undef const reader = new FileReader(); reader.onload = () => res(reader.result); - reader.onerror = (error) => rej(error); + reader.onerror = error => rej(error); reader.readAsDataURL(source.file); }); // we only want the data after the comma // For example: "data:application/pdf;base64,JVBERi0xLjQKJ..." we would only want "JVBERi0xLjQKJ..." - const [first, second] = base64Data.split(","); + const [first, second] = base64Data.split(','); // in the event there is no 'data:application/pdf;base64,' at the beginning of the base64 string // use the entire string instead const data = second ? second : first; const newSource = { - format: "base64", + format: 'base64', base64: data, type: source.type || (source.file ? source.file.type : null), }; return await DefaultController.saveBase64(name, newSource, options); }, - saveBase64: function ( - name: string, - source: FileSource, - options?: FullOptions - ) { - if (source.format !== "base64") { - throw new Error("saveBase64 can only be used with Base64-type sources."); + 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 } = { base64: source.base64, @@ -507,46 +482,43 @@ const DefaultController = { if (source.type) { data._ContentType = source.type; } - const path = "files/" + name; - return CoreManager.getRESTController().request("POST", path, data, options); + const path = 'files/' + name; + return CoreManager.getRESTController().request('POST', path, data, options); }, download: function (uri, options) { if (XHR) { return this.downloadAjax(uri, options); - } else if (process.env.PARSE_BUILD === "node") { + } 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) => { - resp.setEncoding("base64"); - let base64 = ""; - resp.on("data", (data) => (base64 += data)); - resp.on("end", () => { + 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('end', () => { resolve({ base64, - contentType: resp.headers["content-type"], + contentType: resp.headers['content-type'], }); }); }); - req.on("abort", () => { + req.on('abort', () => { resolve({}); }); - req.on("error", reject); + req.on('error', reject); options.requestTask(req); }); } else { - return Promise.reject( - "Cannot make a request: No definition of XMLHttpRequest was found." - ); + return Promise.reject('Cannot make a request: No definition of XMLHttpRequest was found.'); } }, downloadAjax: function (uri, options) { return new Promise((resolve, reject) => { const xhr = new XHR(); - xhr.open("GET", uri, true); - xhr.responseType = "arraybuffer"; + xhr.open('GET', uri, true); + xhr.responseType = 'arraybuffer'; xhr.onerror = function (e) { reject(e); }; @@ -560,7 +532,7 @@ const DefaultController = { const bytes = new Uint8Array(this.response); resolve({ base64: ParseFile.encodeBase64(bytes), - contentType: xhr.getResponseHeader("content-type"), + contentType: xhr.getResponseHeader('content-type'), }); }; options.requestTask(xhr); @@ -570,22 +542,19 @@ const DefaultController = { deleteFile: function (name) { const headers = { - "X-Parse-Application-ID": CoreManager.get("APPLICATION_ID"), - "X-Parse-Master-Key": CoreManager.get("MASTER_KEY"), + 'X-Parse-Application-ID': CoreManager.get('APPLICATION_ID'), + 'X-Parse-Master-Key': CoreManager.get('MASTER_KEY'), }; - let url = CoreManager.get("SERVER_URL"); - if (url[url.length - 1] !== "/") { - url += "/"; + let url = CoreManager.get('SERVER_URL'); + if (url[url.length - 1] !== '/') { + url += '/'; } - url += "files/" + name; + url += 'files/' + name; return CoreManager.getRESTController() - .ajax("DELETE", url, "", headers) - .catch((response) => { + .ajax('DELETE', url, '', headers) + .catch(response => { // TODO: return JSON object in server - if ( - !response || - response === "SyntaxError: Unexpected end of JSON input" - ) { + if (!response || response === 'SyntaxError: Unexpected end of JSON input') { return Promise.resolve(); } else { return CoreManager.getRESTController().handleError(response); diff --git a/src/ParseGeoPoint.js b/src/ParseGeoPoint.js index 8d9006534..001dca8a1 100644 --- a/src/ParseGeoPoint.js +++ b/src/ParseGeoPoint.js @@ -49,7 +49,7 @@ class ParseGeoPoint { ParseGeoPoint._validate(arg1[0], arg1[1]); this._latitude = arg1[0]; this._longitude = arg1[1]; - } else if (typeof arg1 === "object") { + } else if (typeof arg1 === 'object') { ParseGeoPoint._validate(arg1.latitude, arg1.longitude); this._latitude = arg1.latitude; this._longitude = arg1.longitude; @@ -103,7 +103,7 @@ class ParseGeoPoint { toJSON(): { __type: string, latitude: number, longitude: number } { ParseGeoPoint._validate(this._latitude, this._longitude); return { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: this._latitude, longitude: this._longitude, }; @@ -136,10 +136,7 @@ class ParseGeoPoint { // Square of half the straight line chord distance between both points. let a = sinDeltaLatDiv2 * sinDeltaLatDiv2 + - Math.cos(lat1rad) * - Math.cos(lat2rad) * - sinDeltaLongDiv2 * - sinDeltaLongDiv2; + Math.cos(lat1rad) * Math.cos(lat2rad) * sinDeltaLongDiv2 * sinDeltaLongDiv2; a = Math.min(1.0, a); return 2 * Math.asin(Math.sqrt(a)); } @@ -171,32 +168,22 @@ class ParseGeoPoint { if ( isNaN(latitude) || isNaN(longitude) || - typeof latitude !== "number" || - typeof longitude !== "number" + 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.'); } } @@ -207,11 +194,8 @@ class ParseGeoPoint { * @returns {Parse.GeoPoint} User's current location */ static current() { - return navigator.geolocation.getCurrentPosition((location) => { - return new ParseGeoPoint( - location.coords.latitude, - location.coords.longitude - ); + 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 f9d93b8fd..8a5982687 100644 --- a/src/ParseHooks.js +++ b/src/ParseHooks.js @@ -1,25 +1,21 @@ -import CoreManager from "./CoreManager"; -import decode from "./decode"; -import ParseError from "./ParseError"; +import CoreManager from './CoreManager'; +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"); + 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) { @@ -60,71 +56,68 @@ export function remove(hook) { const DefaultController = { get(type, functionName, triggerName) { - let url = "/hooks/" + type; + let url = '/hooks/' + type; if (functionName) { - url += "/" + 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); + return this.sendRequest('PUT', url, hook); }, sendRequest(method, url, body) { return CoreManager.getRESTController() .request(method, url, body, { useMasterKey: true }) - .then((res) => { + .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." - ) + new ParseError(ParseError.INVALID_JSON, 'The server returned an invalid response.') ); }); }, diff --git a/src/ParseInstallation.js b/src/ParseInstallation.js index 2fd45b00d..882214706 100644 --- a/src/ParseInstallation.js +++ b/src/ParseInstallation.js @@ -9,14 +9,14 @@ * @flow */ -import ParseObject from "./ParseObject"; +import ParseObject from './ParseObject'; -import type { AttributeMap } from "./ObjectStateMutations"; +import type { AttributeMap } from './ObjectStateMutations'; export default class Installation extends ParseObject { constructor(attributes: ?AttributeMap) { - super("_Installation"); - if (attributes && typeof attributes === "object") { + super('_Installation'); + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { throw new Error("Can't create an invalid Installation"); } @@ -24,4 +24,4 @@ export default class Installation extends ParseObject { } } -ParseObject.registerSubclass("_Installation", Installation); +ParseObject.registerSubclass('_Installation', Installation); diff --git a/src/ParseLiveQuery.js b/src/ParseLiveQuery.js index 0147fc4d1..d50dcff06 100644 --- a/src/ParseLiveQuery.js +++ b/src/ParseLiveQuery.js @@ -9,9 +9,9 @@ * @flow */ -import EventEmitter from "./EventEmitter"; -import LiveQueryClient from "./LiveQueryClient"; -import CoreManager from "./CoreManager"; +import EventEmitter from './EventEmitter'; +import LiveQueryClient from './LiveQueryClient'; +import CoreManager from './CoreManager'; function getLiveQueryClient(): LiveQueryClient { return CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); @@ -68,7 +68,7 @@ LiveQuery.close = async () => { }; // Register a default onError callback to make sure we do not crash on error -LiveQuery.on("error", () => {}); +LiveQuery.on('error', () => {}); export default LiveQuery; @@ -87,29 +87,27 @@ const DefaultLiveQueryController = { CoreManager.getUserController().currentUserAsync(), CoreManager.getInstallationController().currentInstallationId(), ]); - const sessionToken = currentUser - ? currentUser.getSessionToken() - : undefined; + const sessionToken = currentUser ? currentUser.getSessionToken() : undefined; - let liveQueryServerURL = CoreManager.get("LIVEQUERY_SERVER_URL"); - if (liveQueryServerURL && liveQueryServerURL.indexOf("ws") !== 0) { + let liveQueryServerURL = CoreManager.get('LIVEQUERY_SERVER_URL'); + if (liveQueryServerURL && liveQueryServerURL.indexOf('ws') !== 0) { throw new Error( - "You need to set a proper Parse LiveQuery server url before using LiveQueryClient" + 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' ); } // If we can not find Parse.liveQueryServerURL, we try to extract it from Parse.serverURL if (!liveQueryServerURL) { - const serverURL = CoreManager.get("SERVER_URL"); - const protocol = serverURL.indexOf("https") === 0 ? "wss://" : "ws://"; - const host = serverURL.replace(/^https?:\/\//, ""); + const serverURL = CoreManager.get('SERVER_URL'); + const protocol = serverURL.indexOf('https') === 0 ? 'wss://' : 'ws://'; + const host = serverURL.replace(/^https?:\/\//, ''); liveQueryServerURL = protocol + host; - CoreManager.set("LIVEQUERY_SERVER_URL", liveQueryServerURL); + CoreManager.set('LIVEQUERY_SERVER_URL', liveQueryServerURL); } - const applicationId = CoreManager.get("APPLICATION_ID"); - const javascriptKey = CoreManager.get("JAVASCRIPT_KEY"); - const masterKey = CoreManager.get("MASTER_KEY"); + const applicationId = CoreManager.get('APPLICATION_ID'); + const javascriptKey = CoreManager.get('JAVASCRIPT_KEY'); + const masterKey = CoreManager.get('MASTER_KEY'); defaultLiveQueryClient = new LiveQueryClient({ applicationId, @@ -119,14 +117,14 @@ const DefaultLiveQueryController = { sessionToken, installationId, }); - defaultLiveQueryClient.on("error", (error) => { - LiveQuery.emit("error", error); + defaultLiveQueryClient.on('error', error => { + LiveQuery.emit('error', error); }); - defaultLiveQueryClient.on("open", () => { - LiveQuery.emit("open"); + defaultLiveQueryClient.on('open', () => { + LiveQuery.emit('open'); }); - defaultLiveQueryClient.on("close", () => { - LiveQuery.emit("close"); + defaultLiveQueryClient.on('close', () => { + LiveQuery.emit('close'); }); return defaultLiveQueryClient; }, diff --git a/src/ParseObject.js b/src/ParseObject.js index 7725f4d68..1efb3101c 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -9,17 +9,17 @@ * @flow */ -import CoreManager from "./CoreManager"; -import canBeSerialized from "./canBeSerialized"; -import decode from "./decode"; -import encode from "./encode"; -import escape from "./escape"; -import ParseACL from "./ParseACL"; -import parseDate from "./parseDate"; -import ParseError from "./ParseError"; -import ParseFile from "./ParseFile"; -import { when, continueWhile, resolvingPromise } from "./promiseUtils"; -import { DEFAULT_PIN, PIN_PREFIX } from "./LocalDatastoreUtils"; +import CoreManager from './CoreManager'; +import canBeSerialized from './canBeSerialized'; +import decode from './decode'; +import encode from './encode'; +import escape from './escape'; +import ParseACL from './ParseACL'; +import parseDate from './parseDate'; +import ParseError from './ParseError'; +import ParseFile from './ParseFile'; +import { when, continueWhile, resolvingPromise } from './promiseUtils'; +import { DEFAULT_PIN, PIN_PREFIX } from './LocalDatastoreUtils'; import { opFromJSON, @@ -31,18 +31,18 @@ import { AddUniqueOp, RemoveOp, RelationOp, -} from "./ParseOp"; -import ParseQuery from "./ParseQuery"; -import ParseRelation from "./ParseRelation"; -import * as SingleInstanceStateController from "./SingleInstanceStateController"; -import unique from "./unique"; -import * as UniqueInstanceStateController from "./UniqueInstanceStateController"; -import unsavedChildren from "./unsavedChildren"; +} from './ParseOp'; +import ParseQuery from './ParseQuery'; +import ParseRelation from './ParseRelation'; +import * as SingleInstanceStateController from './SingleInstanceStateController'; +import unique from './unique'; +import * as UniqueInstanceStateController from './UniqueInstanceStateController'; +import unsavedChildren from './unsavedChildren'; -import type { AttributeMap, OpsMap } from "./ObjectStateMutations"; -import type { RequestOptions, FullOptions } from "./RESTController"; +import type { AttributeMap, OpsMap } from './ObjectStateMutations'; +import type { RequestOptions, FullOptions } from './RESTController'; -const uuidv4 = require("uuid/v4"); +const uuidv4 = require('uuid/v4'); export type Pointer = { __type: string, @@ -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 { @@ -78,12 +78,12 @@ if (singleInstance) { } function getServerUrlPath() { - let serverUrl = CoreManager.get("SERVER_URL"); - if (serverUrl[serverUrl.length - 1] !== "/") { - serverUrl += "/"; + let serverUrl = CoreManager.get('SERVER_URL'); + if (serverUrl[serverUrl.length - 1] !== '/') { + serverUrl += '/'; } - const url = serverUrl.replace(/https?:\/\//, ""); - return url.substr(url.indexOf("/")); + const url = serverUrl.replace(/https?:\/\//, ''); + return url.substr(url.indexOf('/')); } /** @@ -116,26 +116,26 @@ class ParseObject { options?: { ignoreValidation: boolean } ) { // Enable legacy initializers - if (typeof this.initialize === "function") { + if (typeof this.initialize === 'function') { this.initialize.apply(this, arguments); } let toSet = null; this._objCount = objectCount++; - if (typeof className === "string") { + if (typeof className === 'string') { this.className = className; - if (attributes && typeof attributes === "object") { + if (attributes && typeof attributes === 'object') { toSet = attributes; } - } else if (className && typeof className === "object") { + } else if (className && typeof className === 'object') { this.className = className.className; toSet = {}; for (const attr in className) { - if (attr !== "className") { + if (attr !== 'className') { toSet[attr] = className[attr]; } } - if (attributes && typeof attributes === "object") { + if (attributes && typeof attributes === 'object') { options = attributes; } } @@ -158,9 +158,7 @@ class ParseObject { get attributes(): AttributeMap { const stateController = CoreManager.getObjectStateController(); - return Object.freeze( - stateController.estimateAttributes(this._getStateIdentifier()) - ); + return Object.freeze(stateController.estimateAttributes(this._getStateIdentifier())); } /** @@ -191,13 +189,13 @@ class ParseObject { * @returns {string} */ _getId(): string { - if (typeof this.id === "string") { + if (typeof this.id === 'string') { return this.id; } - if (typeof this._localId === "string") { + if (typeof this._localId === 'string') { return this._localId; } - const localId = "local" + uuidv4(); + const localId = 'local' + uuidv4(); this._localId = localId; return localId; } @@ -250,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]; }); } @@ -258,15 +256,13 @@ class ParseObject { _getDirtyObjectAttributes(): AttributeMap { const attributes = this.attributes; const stateController = CoreManager.getObjectStateController(); - const objectCache = stateController.getObjectCache( - this._getStateIdentifier() - ); + const objectCache = stateController.getObjectCache(this._getStateIdentifier()); const dirty = {}; for (const attr in attributes) { const val = attributes[attr]; if ( val && - typeof val === "object" && + typeof val === 'object' && !(val instanceof ParseObject) && !(val instanceof ParseFile) && !(val instanceof ParseRelation) @@ -291,7 +287,7 @@ class ParseObject { _toFullJSON(seen?: Array, offline?: boolean): AttributeMap { const json: { [key: string]: mixed } = this.toJSON(seen, offline); - json.__type = "Object"; + json.__type = 'Object'; json.className = this.className; return json; } @@ -307,8 +303,8 @@ class ParseObject { for (let i = 0; i < pending.length; i += 1) { for (const field in pending[i]) { // Dot notation operations are handled later - if (field.includes(".")) { - const fieldName = field.split(".")[0]; + if (field.includes('.')) { + const fieldName = field.split('.')[0]; if (fieldName === attr) { isDotNotation = true; break; @@ -327,13 +323,13 @@ class ParseObject { } _getSaveParams(): SaveParams { - const method = this.id ? "PUT" : "POST"; + const method = this.id ? 'PUT' : 'POST'; const body = this._getSaveJSON(); - let path = "classes/" + this.className; + let path = 'classes/' + this.className; if (this.id) { - path += "/" + this.id; - } else if (this.className === "_User") { - path = "users"; + path += '/' + this.id; + } else if (this.className === '_User') { + path = 'users'; } return { method, @@ -350,19 +346,19 @@ class ParseObject { stateController.initializeState(this._getStateIdentifier()); const decoded = {}; for (const attr in serverData) { - if (attr === "ACL") { + if (attr === 'ACL') { decoded[attr] = new ParseACL(serverData[attr]); - } else if (attr !== "objectId") { + } else if (attr !== 'objectId') { decoded[attr] = decode(serverData[attr]); if (decoded[attr] instanceof ParseRelation) { decoded[attr]._ensureParentAndKey(this, attr); } } } - if (decoded.createdAt && typeof decoded.createdAt === "string") { + if (decoded.createdAt && typeof decoded.createdAt === 'string') { decoded.createdAt = parseDate(decoded.createdAt); } - if (decoded.updatedAt && typeof decoded.updatedAt === "string") { + if (decoded.updatedAt && typeof decoded.updatedAt === 'string') { decoded.updatedAt = parseDate(decoded.updatedAt); } if (!decoded.updatedAt && decoded.createdAt) { @@ -383,9 +379,7 @@ class ParseObject { if (this._localId && serverId) { if (singleInstance) { const stateController = CoreManager.getObjectStateController(); - const oldState = stateController.removeState( - this._getStateIdentifier() - ); + const oldState = stateController.removeState(this._getStateIdentifier()); this.id = serverId; delete this._localId; if (oldState) { @@ -406,20 +400,17 @@ class ParseObject { for (attr in pending) { if (pending[attr] instanceof RelationOp) { changes[attr] = pending[attr].applyTo(undefined, this, attr); - } else if (!(attr in response) && !attr.includes(".")) { + } else if (!(attr in response) && !attr.includes('.')) { // Only SetOps and UnsetOps should not come back with results changes[attr] = pending[attr].applyTo(undefined); } } 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") { + } else if (attr === 'ACL') { changes[attr] = new ParseACL(response[attr]); - } else if (attr !== "objectId") { + } else if (attr !== 'objectId') { const val = decode(response[attr]); if (val && Object.getPrototypeOf(val) === Object.prototype) { changes[attr] = { ...this.attributes[attr], ...val }; @@ -463,15 +454,12 @@ class ParseObject { * @returns {object} */ toJSON(seen: Array | void, offline?: boolean): AttributeMap { - const seenEntry = this.id ? this.className + ":" + this.id : this; + const seenEntry = this.id ? this.className + ':' + this.id : this; seen = seen || [seenEntry]; const json = {}; const attrs = this.attributes; for (const attr in attrs) { - if ( - (attr === "createdAt" || attr === "updatedAt") && - attrs[attr].toJSON - ) { + if ((attr === 'createdAt' || attr === 'updatedAt') && attrs[attr].toJSON) { json[attr] = attrs[attr].toJSON(); } else { json[attr] = encode(attrs[attr], false, false, seen, offline); @@ -502,7 +490,7 @@ class ParseObject { other instanceof ParseObject && this.className === other.className && this.id === other.id && - typeof this.id !== "undefined" + typeof this.id !== 'undefined' ); } @@ -577,10 +565,10 @@ class ParseObject { */ toPointer(): Pointer { if (!this.id) { - throw new Error("Cannot create a pointer to an unsaved ParseObject"); + throw new Error('Cannot create a pointer to an unsaved ParseObject'); } return { - __type: "Pointer", + __type: 'Pointer', className: this.className, objectId: this.id, }; @@ -593,10 +581,10 @@ class ParseObject { */ toOfflinePointer(): Pointer { if (!this._localId) { - throw new Error("Cannot create a offline pointer to a saved ParseObject"); + throw new Error('Cannot create a offline pointer to a saved ParseObject'); } return { - __type: "Object", + __type: 'Object', className: this.className, _localId: this._localId, }; @@ -622,7 +610,7 @@ class ParseObject { const value = this.get(attr); if (value) { if (!(value instanceof ParseRelation)) { - throw new Error("Called relation() on non-relation field " + attr); + throw new Error('Called relation() on non-relation field ' + attr); } value._ensureParentAndKey(this, attr); return value; @@ -639,11 +627,11 @@ class ParseObject { escape(attr: string): string { let val = this.attributes[attr]; if (val == null) { - return ""; + return ''; } - if (typeof val !== "string") { - if (typeof val.toString !== "function") { - return ""; + if (typeof val !== 'string') { + if (typeof val.toString !== 'function') { + return ''; } val = val.toString(); } @@ -698,10 +686,10 @@ class ParseObject { set(key: mixed, value: mixed, options?: mixed): ParseObject | boolean { let changes = {}; const newOps = {}; - if (key && typeof key === "object") { + if (key && typeof key === 'object') { changes = key; options = value; - } else if (typeof key === "string") { + } else if (typeof key === 'string') { changes[key] = value; } else { return this; @@ -709,17 +697,17 @@ class ParseObject { options = options || {}; let readonly = []; - if (typeof this.constructor.readOnlyAttributes === "function") { + if (typeof this.constructor.readOnlyAttributes === 'function') { readonly = readonly.concat(this.constructor.readOnlyAttributes()); } for (const k in changes) { - if (k === "createdAt" || k === "updatedAt") { + if (k === 'createdAt' || k === 'updatedAt') { // This property is read-only, but for legacy reasons we silently // ignore it continue; } if (readonly.indexOf(k) > -1) { - throw new Error("Cannot modify readonly attribute: " + k); + throw new Error('Cannot modify readonly attribute: ' + k); } if (options.unset) { newOps[k] = new UnsetOp(); @@ -727,17 +715,17 @@ class ParseObject { newOps[k] = changes[k]; } else if ( changes[k] && - typeof changes[k] === "object" && - typeof changes[k].__op === "string" + typeof changes[k] === 'object' && + typeof changes[k].__op === 'string' ) { newOps[k] = opFromJSON(changes[k]); - } else if (k === "objectId" || k === "id") { - if (typeof changes[k] === "string") { + } else if (k === 'objectId' || k === 'id') { + if (typeof changes[k] === 'string') { this.id = changes[k]; } } else if ( - k === "ACL" && - typeof changes[k] === "object" && + k === 'ACL' && + typeof changes[k] === 'object' && !(changes[k] instanceof ParseACL) ) { newOps[k] = new SetOp(new ParseACL(changes[k])); @@ -754,8 +742,8 @@ class ParseObject { // Only set nested fields if exists const serverData = this._getServerData(); - if (typeof key === "string" && key.includes(".")) { - const field = key.split(".")[0]; + if (typeof key === 'string' && key.includes('.')) { + const field = key.split('.')[0]; if (!serverData[field]) { return this; } @@ -765,11 +753,7 @@ class ParseObject { const newValues = {}; for (const attr in newOps) { if (newOps[attr] instanceof RelationOp) { - newValues[attr] = newOps[attr].applyTo( - currentAttributes[attr], - this, - attr - ); + newValues[attr] = newOps[attr].applyTo(currentAttributes[attr], this, attr); } else if (!(newOps[attr] instanceof UnsetOp)) { newValues[attr] = newOps[attr].applyTo(currentAttributes[attr]); } @@ -779,7 +763,7 @@ class ParseObject { if (!options.ignoreValidation) { const validation = this.validate(newValues); if (validation) { - if (typeof options.error === "function") { + if (typeof options.error === 'function') { options.error(this, validation); } return false; @@ -806,10 +790,7 @@ class ParseObject { * @param options * @returns {(ParseObject | boolean)} */ - unset( - attr: string, - options?: { [opt: string]: mixed } - ): ParseObject | boolean { + unset(attr: string, options?: { [opt: string]: mixed }): ParseObject | boolean { options = options || {}; options.unset = true; return this.set(attr, null, options); @@ -824,11 +805,11 @@ class ParseObject { * @returns {(ParseObject|boolean)} */ increment(attr: string, amount?: number): ParseObject | boolean { - if (typeof amount === "undefined") { + if (typeof amount === 'undefined') { amount = 1; } - if (typeof amount !== "number") { - throw new Error("Cannot increment by a non-numeric amount."); + if (typeof amount !== 'number') { + throw new Error('Cannot increment by a non-numeric amount.'); } return this.set(attr, new IncrementOp(amount)); } @@ -842,11 +823,11 @@ class ParseObject { * @returns {(ParseObject | boolean)} */ decrement(attr: string, amount?: number): ParseObject | boolean { - if (typeof amount === "undefined") { + if (typeof amount === 'undefined') { amount = 1; } - if (typeof amount !== "number") { - throw new Error("Cannot decrement by a non-numeric amount."); + if (typeof amount !== 'number') { + throw new Error('Cannot decrement by a non-numeric amount.'); } return this.set(attr, new IncrementOp(amount * -1)); } @@ -954,7 +935,7 @@ class ParseObject { clone.className = this.className; } let attributes = this.attributes; - if (typeof this.constructor.readOnlyAttributes === "function") { + if (typeof this.constructor.readOnlyAttributes === 'function') { const readonly = this.constructor.readOnlyAttributes() || []; // Attributes are frozen, so we have to rebuild an object, // rather than delete readonly keys @@ -990,10 +971,7 @@ class ParseObject { const stateController = CoreManager.getObjectStateController(); if (stateController) { - stateController.duplicateState( - this._getStateIdentifier(), - clone._getStateIdentifier() - ); + stateController.duplicateState(this._getStateIdentifier(), clone._getStateIdentifier()); } return clone; } @@ -1074,8 +1052,8 @@ class ParseObject { * @see Parse.Object#set */ 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."); + if (attrs.hasOwnProperty('ACL') && !(attrs.ACL instanceof ParseACL)) { + 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)) { @@ -1092,7 +1070,7 @@ class ParseObject { * @see Parse.Object#get */ getACL(): ?ParseACL { - const acl = this.get("ACL"); + const acl = this.get('ACL'); if (acl instanceof ParseACL) { return acl; } @@ -1108,7 +1086,7 @@ class ParseObject { * @see Parse.Object#set */ setACL(acl: ParseACL, options?: mixed): ParseObject | boolean { - return this.set("ACL", acl, options); + return this.set('ACL', acl, options); } /** @@ -1121,12 +1099,10 @@ class ParseObject { if (keys.length) { keysToRevert = []; for (const key of keys) { - if (typeof key === "string") { + 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.'); } } } @@ -1141,8 +1117,8 @@ class ParseObject { clear(): ParseObject | boolean { const attributes = this.attributes; const erasable = {}; - let readonly = ["createdAt", "updatedAt"]; - if (typeof this.constructor.readOnlyAttributes === "function") { + let readonly = ['createdAt', 'updatedAt']; + if (typeof this.constructor.readOnlyAttributes === 'function') { readonly = readonly.concat(this.constructor.readOnlyAttributes()); } for (const attr in attributes) { @@ -1173,22 +1149,19 @@ class ParseObject { fetch(options: RequestOptions): Promise { options = options || {}; const fetchOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { fetchOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { fetchOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { fetchOptions.context = options.context; } - if (options.hasOwnProperty("include")) { + 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 { @@ -1221,10 +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); @@ -1295,9 +1265,9 @@ class ParseObject { ): Promise { let attrs; let options; - if (typeof arg1 === "object" || typeof arg1 === "undefined") { + if (typeof arg1 === 'object' || typeof arg1 === 'undefined') { attrs = arg1; - if (typeof arg2 === "object") { + if (typeof arg2 === 'object') { options = arg2; } } else { @@ -1316,30 +1286,20 @@ class ParseObject { options = options || {}; const saveOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { saveOptions.useMasterKey = !!options.useMasterKey; } - if ( - options.hasOwnProperty("sessionToken") && - typeof options.sessionToken === "string" - ) { + if (options.hasOwnProperty('sessionToken') && typeof options.sessionToken === 'string') { saveOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("installationId") && - typeof options.installationId === "string" - ) { + if (options.hasOwnProperty('installationId') && typeof options.installationId === 'string') { saveOptions.installationId = options.installationId; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { saveOptions.context = options.context; } const controller = CoreManager.getObjectController(); - const unsaved = - options.cascadeSave !== false ? unsavedChildren(this) : null; + const unsaved = options.cascadeSave !== false ? unsavedChildren(this) : null; return controller.save(unsaved, saveOptions).then(() => { return controller.save(this, saveOptions); }); @@ -1362,16 +1322,13 @@ class ParseObject { destroy(options: RequestOptions): Promise { options = options || {}; const destroyOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { destroyOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { destroyOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { destroyOptions.context = options.context; } if (!this.id) { @@ -1426,9 +1383,7 @@ class ParseObject { async isPinned(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } const objectKey = localDatastore.getKeyForObject(this); const pin = await localDatastore.fromPinWithName(objectKey); @@ -1484,12 +1439,12 @@ class ParseObject { async fetchFromLocalDatastore(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - throw new Error("Parse.enableLocalDatastore() must be called first"); + throw new Error('Parse.enableLocalDatastore() must be called first'); } const objectKey = localDatastore.getKeyForObject(this); const pinned = await localDatastore._serializeObject(objectKey); if (!pinned) { - throw new Error("Cannot fetch an unsaved ParseObject"); + throw new Error('Cannot fetch an unsaved ParseObject'); } const result = ParseObject.fromJSON(pinned); this._finishFetch(result.toJSON()); @@ -1532,13 +1487,13 @@ class ParseObject { */ static fetchAll(list: Array, options: RequestOptions = {}) { const queryOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { queryOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { queryOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty("include")) { + if (options.hasOwnProperty('include')) { queryOptions.include = ParseObject.handleIncludeOptions(options); } return CoreManager.getObjectController().fetch(list, true, queryOptions); @@ -1645,13 +1600,13 @@ class ParseObject { options = options || {}; const queryOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { queryOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { queryOptions.sessionToken = options.sessionToken; } - if (options.hasOwnProperty("include")) { + if (options.hasOwnProperty('include')) { queryOptions.include = ParseObject.handleIncludeOptions(options); } return CoreManager.getObjectController().fetch(list, false, queryOptions); @@ -1660,7 +1615,7 @@ class ParseObject { 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 { @@ -1721,22 +1676,16 @@ class ParseObject { */ static destroyAll(list: Array, options = {}) { const destroyOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { destroyOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { destroyOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("batchSize") && - typeof options.batchSize === "number" - ) { + if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { destroyOptions.batchSize = options.batchSize; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { destroyOptions.context = options.context; } return CoreManager.getObjectController().destroy(list, destroyOptions); @@ -1762,22 +1711,16 @@ class ParseObject { */ static saveAll(list: Array, options: RequestOptions = {}) { const saveOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { saveOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { saveOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("batchSize") && - typeof options.batchSize === "number" - ) { + if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { saveOptions.batchSize = options.batchSize; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { saveOptions.context = options.context; } return CoreManager.getObjectController().save(list, saveOptions); @@ -1814,13 +1757,13 @@ class ParseObject { */ static fromJSON(json: any, override?: boolean) { if (!json.className) { - throw new Error("Cannot create an object without a className"); + throw new Error('Cannot create an object without a className'); } const constructor = classMap[json.className]; const o = constructor ? new constructor() : new ParseObject(json.className); const otherAttributes = {}; for (const attr in json) { - if (attr !== "className" && attr !== "__type") { + if (attr !== 'className' && attr !== '__type') { otherAttributes[attr] = json[attr]; } } @@ -1830,7 +1773,7 @@ class ParseObject { o.id = otherAttributes.objectId; } let preserved = null; - if (typeof o._preserveFieldsOnFetch === "function") { + if (typeof o._preserveFieldsOnFetch === 'function') { preserved = o._preserveFieldsOnFetch(); } o._clearServerData(); @@ -1855,16 +1798,16 @@ class ParseObject { * @param {Function} constructor The subclass */ static registerSubclass(className: string, constructor: any) { - if (typeof className !== "string") { - throw new TypeError("The first argument must be a valid class name."); + if (typeof className !== 'string') { + throw new TypeError('The first argument must be a valid class name.'); } - if (typeof constructor === "undefined") { - throw new TypeError("You must supply a subclass constructor."); + if (typeof constructor === 'undefined') { + throw new TypeError('You must supply a subclass constructor.'); } - if (typeof constructor !== "function") { + if (typeof constructor !== 'function') { throw new TypeError( - "You must register the subclass constructor. " + - "Did you attempt to register an instance of the subclass?" + 'You must register the subclass constructor. ' + + 'Did you attempt to register an instance of the subclass?' ); } classMap[className] = constructor; @@ -1911,26 +1854,21 @@ class ParseObject { * @returns {Parse.Object} A new subclass of Parse.Object. */ static extend(className: any, protoProps: any, classProps: any) { - if (typeof className !== "string") { - if (className && typeof className.className === "string") { + if (typeof className !== 'string') { + 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; - if ( - adjustedClassName === "User" && - CoreManager.get("PERFORM_USER_REWRITE") - ) { - adjustedClassName = "_User"; + if (adjustedClassName === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { + adjustedClassName = '_User'; } let parentProto = ParseObject.prototype; - if (this.hasOwnProperty("__super__") && this.__super__) { + if (this.hasOwnProperty('__super__') && this.__super__) { parentProto = this.prototype; } else if (classMap[adjustedClassName]) { parentProto = classMap[adjustedClassName].prototype; @@ -1939,11 +1877,11 @@ class ParseObject { this.className = adjustedClassName; this._objCount = objectCount++; // Enable legacy initializers - if (typeof this.initialize === "function") { + if (typeof this.initialize === 'function') { 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"); } @@ -1963,7 +1901,7 @@ class ParseObject { if (protoProps) { for (const prop in protoProps) { - if (prop !== "className") { + if (prop !== 'className') { Object.defineProperty(ParseObjectSubclass.prototype, prop, { value: protoProps[prop], enumerable: false, @@ -1976,7 +1914,7 @@ class ParseObject { if (classProps) { for (const prop in classProps) { - if (prop !== "className") { + if (prop !== 'className') { Object.defineProperty(ParseObjectSubclass, prop, { value: classProps[prop], enumerable: false, @@ -1988,20 +1926,10 @@ class ParseObject { } ParseObjectSubclass.extend = function (name, protoProps, classProps) { - if (typeof name === "string") { - return ParseObject.extend.call( - ParseObjectSubclass, - name, - protoProps, - classProps - ); + if (typeof name === 'string') { + return ParseObject.extend.call(ParseObjectSubclass, name, protoProps, classProps); } - return ParseObject.extend.call( - ParseObjectSubclass, - adjustedClassName, - name, - protoProps - ); + return ParseObject.extend.call(ParseObjectSubclass, adjustedClassName, name, protoProps); }; ParseObjectSubclass.createWithoutData = ParseObject.createWithoutData; @@ -2056,9 +1984,7 @@ class ParseObject { static pinAll(objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return ParseObject.pinAllWithName(DEFAULT_PIN, objects); } @@ -2081,15 +2007,10 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the pin completes. * @static */ - static pinAllWithName( - name: string, - objects: Array - ): Promise { + static pinAllWithName(name: string, objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return localDatastore._handlePinAllWithName(name, objects); } @@ -2109,9 +2030,7 @@ class ParseObject { static unPinAll(objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return ParseObject.unPinAllWithName(DEFAULT_PIN, objects); } @@ -2128,15 +2047,10 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the unPin completes. * @static */ - static unPinAllWithName( - name: string, - objects: Array - ): Promise { + static unPinAllWithName(name: string, objects: Array): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return localDatastore._handleUnPinAllWithName(name, objects); } @@ -2154,9 +2068,7 @@ class ParseObject { static unPinAllObjects(): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return localDatastore.unPinWithName(DEFAULT_PIN); } @@ -2176,9 +2088,7 @@ class ParseObject { static unPinAllObjectsWithName(name: string): Promise { const localDatastore = CoreManager.getLocalDatastore(); if (!localDatastore.isEnabled) { - return Promise.reject( - "Parse.enableLocalDatastore() must be called first" - ); + return Promise.reject('Parse.enableLocalDatastore() must be called first'); } return localDatastore.unPinWithName(PIN_PREFIX + name); } @@ -2200,7 +2110,7 @@ const DefaultController = { let className = null; const results = []; let error = null; - target.forEach((el) => { + target.forEach(el => { if (error) { return; } @@ -2210,14 +2120,11 @@ const DefaultController = { if (className !== el.className) { error = new ParseError( ParseError.INVALID_CLASS_NAME, - "All objects should be of the same class" + 'All objects should be of the same class' ); } 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); @@ -2229,14 +2136,14 @@ const DefaultController = { return Promise.reject(error); } const query = new ParseQuery(className); - query.containedIn("objectId", ids); + query.containedIn('objectId', ids); if (options && options.include) { 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++) { @@ -2244,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.') ); } } @@ -2271,10 +2175,7 @@ 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" - ) + new ParseError(ParseError.MISSING_OBJECT_ID, 'Object does not have an ID') ); } const RESTController = CoreManager.getRESTController(); @@ -2283,11 +2184,11 @@ const DefaultController = { params.include = options.include.join(); } return RESTController.request( - "GET", - "classes/" + target.className + "/" + target._getId(), + 'GET', + 'classes/' + target.className + '/' + target._getId(), params, options - ).then(async (response) => { + ).then(async response => { target._clearPendingOps(); target._clearServerData(); target._finishFetch(response); @@ -2303,9 +2204,7 @@ const DefaultController = { options: RequestOptions ): Promise | ParseObject> { const batchSize = - options && options.batchSize - ? options.batchSize - : CoreManager.get("REQUEST_BATCH_SIZE"); + options && options.batchSize ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); const localDatastore = CoreManager.getLocalDatastore(); const RESTController = CoreManager.getRESTController(); @@ -2314,7 +2213,7 @@ const DefaultController = { return Promise.resolve([]); } const batches = [[]]; - target.forEach((obj) => { + target.forEach(obj => { if (!obj.id) { return; } @@ -2329,33 +2228,25 @@ const DefaultController = { } let deleteCompleted = Promise.resolve(); const errors = []; - batches.forEach((batch) => { + batches.forEach(batch => { deleteCompleted = deleteCompleted.then(() => { return RESTController.request( - "POST", - "batch", + 'POST', + 'batch', { - requests: batch.map((obj) => { + requests: batch.map(obj => { return { - method: "DELETE", - path: - getServerUrlPath() + - "classes/" + - obj.className + - "/" + - obj._getId(), + method: 'DELETE', + path: getServerUrlPath() + 'classes/' + obj.className + '/' + obj._getId(), body: {}, }; }), }, options - ).then((results) => { + ).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 - ); + if (results[i] && results[i].hasOwnProperty('error')) { + const err = new ParseError(results[i].error.code, results[i].error.error); err.object = batch[i]; errors.push(err); } @@ -2376,8 +2267,8 @@ const DefaultController = { }); } else if (target instanceof ParseObject) { return RESTController.request( - "DELETE", - "classes/" + target.className + "/" + target._getId(), + 'DELETE', + 'classes/' + target.className + '/' + target._getId(), {}, options ).then(async () => { @@ -2388,14 +2279,9 @@ const DefaultController = { return Promise.resolve(target); }, - save( - target: ParseObject | Array, - options: RequestOptions - ) { + save(target: ParseObject | Array, options: RequestOptions) { const batchSize = - options && options.batchSize - ? options.batchSize - : CoreManager.get("REQUEST_BATCH_SIZE"); + options && options.batchSize ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); const localDatastore = CoreManager.getLocalDatastore(); const mapIdForPin = {}; @@ -2419,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) { @@ -2436,7 +2322,7 @@ const DefaultController = { () => { const batch = []; const nextPending = []; - pending.forEach((el) => { + pending.forEach(el => { if (batch.length < batchSize && canBeSerialized(el)) { batch.push(el); } else { @@ -2446,10 +2332,7 @@ const DefaultController = { pending = nextPending; if (batch.length < 1) { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - "Tried to save a batch with a cycle." - ) + new ParseError(ParseError.OTHER_CAUSE, 'Tried to save a batch with a cycle.') ); } @@ -2463,23 +2346,17 @@ const DefaultController = { batchReady.push(ready); const task = function () { ready.resolve(); - return batchReturned.then((responses) => { - if (responses[index].hasOwnProperty("success")) { + 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") - ) { + if (!objectError && responses[index].hasOwnProperty('error')) { const serverError = responses[index].error; - objectError = new ParseError( - serverError.code, - serverError.error - ); + objectError = new ParseError(serverError.code, serverError.error); // Cancel the rest of the save pending = []; } @@ -2488,19 +2365,17 @@ const DefaultController = { }); }; stateController.pushPendingState(obj._getStateIdentifier()); - batchTasks.push( - stateController.enqueueTask(obj._getStateIdentifier(), task) - ); + batchTasks.push(stateController.enqueueTask(obj._getStateIdentifier(), task)); }); when(batchReady) .then(() => { // Kick off the batch request return RESTController.request( - "POST", - "batch", + 'POST', + 'batch', { - requests: batch.map((obj) => { + requests: batch.map(obj => { const params = obj._getSaveParams(); params.path = getServerUrlPath() + params.path; return params; @@ -2509,10 +2384,8 @@ const DefaultController = { 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); @@ -2522,10 +2395,7 @@ const DefaultController = { return Promise.reject(objectError); } for (const object of target) { - await localDatastore._updateLocalIdForObject( - mapIdForPin[object.id], - object - ); + await localDatastore._updateLocalIdForObject(mapIdForPin[object.id], object); await localDatastore._updateObjectIfPinned(object); } return Promise.resolve(target); @@ -2539,18 +2409,13 @@ const DefaultController = { const targetCopy = target; const task = function () { const params = targetCopy._getSaveParams(); - return RESTController.request( - params.method, - params.path, - params.body, - options - ).then( - (response) => { + return RESTController.request(params.method, params.path, params.body, options).then( + response => { const status = response._status; delete response._status; targetCopy._handleSaveResponse(response, status); }, - (error) => { + error => { targetCopy._handleSaveError(); return Promise.reject(error); } @@ -2558,18 +2423,16 @@ const DefaultController = { }; 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(); }, diff --git a/src/ParseOp.js b/src/ParseOp.js index f5973e0c0..0029916e7 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -9,49 +9,49 @@ * @flow */ -import arrayContainsObject from "./arrayContainsObject"; -import decode from "./decode"; -import encode from "./encode"; -import ParseObject from "./ParseObject"; -import ParseRelation from "./ParseRelation"; -import unique from "./unique"; +import arrayContainsObject from './arrayContainsObject'; +import decode from './decode'; +import encode from './encode'; +import ParseObject from './ParseObject'; +import ParseRelation from './ParseRelation'; +import unique from './unique'; export function opFromJSON(json: { [key: string]: any }): ?Op { if (!json || !json.__op) { return null; } switch (json.__op) { - case "Delete": + case 'Delete': return new UnsetOp(); - case "Increment": + case 'Increment': return new IncrementOp(json.amount); - case "Add": + case 'Add': return new AddOp(decode(json.objects)); - case "AddUnique": + case 'AddUnique': return new AddUniqueOp(decode(json.objects)); - case "Remove": + case 'Remove': return new RemoveOp(decode(json.objects)); - case "AddRelation": { + case 'AddRelation': { const toAdd = decode(json.objects); if (!Array.isArray(toAdd)) { return new RelationOp([], []); } return new RelationOp(toAdd, []); } - case "RemoveRelation": { + case 'RemoveRelation': { const toRemove = decode(json.objects); if (!Array.isArray(toRemove)) { return new RelationOp([], []); } return new RelationOp([], toRemove); } - case "Batch": { + case 'Batch': { let toAdd = []; let toRemove = []; for (let i = 0; i < json.ops.length; i++) { - if (json.ops[i].__op === "AddRelation") { + if (json.ops[i].__op === 'AddRelation') { toAdd = toAdd.concat(decode(json.ops[i].objects)); - } else if (json.ops[i].__op === "RemoveRelation") { + } else if (json.ops[i].__op === 'RemoveRelation') { toRemove = toRemove.concat(decode(json.ops[i].objects)); } } @@ -99,7 +99,7 @@ export class UnsetOp extends Op { } toJSON(): { __op: string } { - return { __op: "Delete" }; + return { __op: 'Delete' }; } } @@ -108,20 +108,18 @@ 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." - ); + if (typeof amount !== 'number') { + throw new TypeError('Increment Op must be initialized with a numeric amount.'); } this._amount = amount; } applyTo(value: ?mixed): number { - if (typeof value === "undefined") { + if (typeof value === 'undefined') { return this._amount; } - if (typeof value !== "number") { - throw new TypeError("Cannot increment a non-numeric value."); + if (typeof value !== 'number') { + throw new TypeError('Cannot increment a non-numeric value.'); } return this._amount + value; } @@ -139,11 +137,11 @@ export class IncrementOp extends Op { if (previous instanceof IncrementOp) { return new IncrementOp(this.applyTo(previous._amount)); } - throw new Error("Cannot merge Increment Op with the previous Op"); + throw new Error('Cannot merge Increment Op with the previous Op'); } toJSON(): { __op: string, amount: number } { - return { __op: "Increment", amount: this._amount }; + return { __op: 'Increment', amount: this._amount }; } } @@ -162,7 +160,7 @@ export class AddOp extends Op { if (Array.isArray(value)) { return value.concat(this._value); } - throw new Error("Cannot add elements to a non-array value"); + throw new Error('Cannot add elements to a non-array value'); } mergeWith(previous: Op): Op { @@ -178,11 +176,11 @@ export class AddOp extends Op { if (previous instanceof AddOp) { return new AddOp(this.applyTo(previous._value)); } - throw new Error("Cannot merge Add Op with the previous Op"); + throw new Error('Cannot merge Add Op with the previous Op'); } toJSON(): { __op: string, objects: mixed } { - return { __op: "Add", objects: encode(this._value, false, true) }; + 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); @@ -213,7 +211,7 @@ export class AddUniqueOp extends Op { }); return value.concat(toAdd); } - throw new Error("Cannot add elements to a non-array value"); + throw new Error('Cannot add elements to a non-array value'); } mergeWith(previous: Op): Op { @@ -229,11 +227,11 @@ export class AddUniqueOp extends Op { if (previous instanceof AddUniqueOp) { return new AddUniqueOp(this.applyTo(previous._value)); } - throw new Error("Cannot merge AddUnique Op with the previous Op"); + throw new Error('Cannot merge AddUnique Op with the previous Op'); } toJSON(): { __op: string, objects: mixed } { - return { __op: "AddUnique", objects: encode(this._value, false, true) }; + return { __op: 'AddUnique', objects: encode(this._value, false, true) }; } } @@ -260,10 +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--; } @@ -272,7 +267,7 @@ export class RemoveOp extends Op { } return removed; } - throw new Error("Cannot remove elements from a non-array value"); + throw new Error('Cannot remove elements from a non-array value'); } mergeWith(previous: Op): Op { @@ -300,11 +295,11 @@ export class RemoveOp extends Op { } return new RemoveOp(uniques); } - throw new Error("Cannot merge Remove Op with the previous Op"); + throw new Error('Cannot merge Remove Op with the previous Op'); } toJSON(): { __op: string, objects: mixed } { - return { __op: "Remove", objects: encode(this._value, false, true) }; + return { __op: 'Remove', objects: encode(this._value, false, true) }; } } @@ -313,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; @@ -330,42 +322,36 @@ export class RelationOp extends Op { } _extractId(obj: string | ParseObject): string { - if (typeof obj === "string") { + if (typeof obj === 'string') { 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; } if (this._targetClassName !== obj.className) { throw new Error( - "Tried to create a Relation with 2 different object types: " + + 'Tried to create a Relation with 2 different object types: ' + this._targetClassName + - " and " + + ' and ' + obj.className + - "." + '.' ); } return obj.id; } - applyTo( - value: mixed, - object?: { className: string, id: ?string }, - key?: string - ): ?ParseRelation { + 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" + '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) { + if (object.id && object.id.indexOf('local') === 0) { parent._localId = object.id; } else if (object.id) { parent.id = object.id; @@ -379,11 +365,11 @@ export class RelationOp extends Op { if (value.targetClassName) { if (this._targetClassName !== value.targetClassName) { throw new Error( - "Related object must be a " + + 'Related object must be a ' + value.targetClassName + - ", but a " + + ', but a ' + this._targetClassName + - " was passed in." + ' was passed in.' ); } } else { @@ -392,7 +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'); } } @@ -400,33 +386,27 @@ export class RelationOp extends Op { if (!previous) { return this; } else if (previous instanceof UnsetOp) { - throw new Error("You cannot modify a relation after deleting it."); - } else if ( - previous instanceof SetOp && - previous._value instanceof ParseRelation - ) { + throw new Error('You cannot modify a relation after deleting it.'); + } 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 " + + 'Related object must be of class ' + previous._targetClassName + - ", but " + - (this._targetClassName || "null") + - " was passed in." + ', 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); @@ -434,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); @@ -451,13 +431,13 @@ export class RelationOp extends Op { newRelation._targetClassName = this._targetClassName; return newRelation; } - throw new Error("Cannot merge Relation Op with the previous Op"); + throw new Error('Cannot merge Relation Op with the previous Op'); } toJSON(): { __op?: string, objects?: mixed, ops?: mixed } { - const idToPointer = (id) => { + const idToPointer = id => { return { - __type: "Pointer", + __type: 'Pointer', className: this._targetClassName, objectId: id, }; @@ -469,15 +449,15 @@ export class RelationOp extends Op { if (this.relationsToAdd.length > 0) { pointers = this.relationsToAdd.map(idToPointer); - adds = { __op: "AddRelation", objects: pointers }; + adds = { __op: 'AddRelation', objects: pointers }; } if (this.relationsToRemove.length > 0) { pointers = this.relationsToRemove.map(idToPointer); - removes = { __op: "RemoveRelation", objects: pointers }; + removes = { __op: 'RemoveRelation', objects: pointers }; } if (adds && removes) { - return { __op: "Batch", ops: [adds, removes] }; + return { __op: 'Batch', ops: [adds, removes] }; } return adds || removes || {}; diff --git a/src/ParsePolygon.js b/src/ParsePolygon.js index 001db1250..b817be8a8 100644 --- a/src/ParsePolygon.js +++ b/src/ParsePolygon.js @@ -9,7 +9,7 @@ * @flow */ -import ParseGeoPoint from "./ParseGeoPoint"; +import ParseGeoPoint from './ParseGeoPoint'; /** * Creates a new Polygon with any of the following forms:
@@ -63,7 +63,7 @@ class ParsePolygon { toJSON(): { __type: string, coordinates: Array> } { ParsePolygon._validate(this._coordinates); return { - __type: "Polygon", + __type: 'Polygon', coordinates: this._coordinates, }; } @@ -75,10 +75,7 @@ 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; @@ -124,11 +121,7 @@ class ParsePolygon { } 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]; @@ -136,9 +129,7 @@ class ParsePolygon { const intersect = startY > point.longitude != endY > point.longitude && - point.latitude < - ((endX - startX) * (point.longitude - startY)) / (endY - startY) + - startX; + point.latitude < ((endX - startX) * (point.longitude - startY)) / (endY - startY) + startX; if (intersect) { inside = !inside; @@ -154,14 +145,12 @@ class ParsePolygon { * @throws {TypeError} * @returns {number[][]} Array of coordinates if validated. */ - static _validate( - coords: Array> | Array - ): Array> { + static _validate(coords: Array> | Array): Array> { if (!Array.isArray(coords)) { - throw new TypeError("Coordinates must be an Array"); + throw new TypeError('Coordinates must be an Array'); } if (coords.length < 3) { - throw new TypeError("Polygon must have at least 3 GeoPoints or Points"); + throw new TypeError('Polygon must have at least 3 GeoPoints or Points'); } const points = []; for (let i = 0; i < coords.length; i += 1) { @@ -172,9 +161,7 @@ class ParsePolygon { } else if (Array.isArray(coord) && coord.length === 2) { geoPoint = new ParseGeoPoint(coord[0], coord[1]); } else { - throw new TypeError( - "Coordinates must be an Array of GeoPoints or Points" - ); + throw new TypeError('Coordinates must be an Array of GeoPoints or Points'); } points.push([geoPoint.latitude, geoPoint.longitude]); } diff --git a/src/ParseQuery.js b/src/ParseQuery.js index dca6bb38a..62c63293b 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -9,17 +9,17 @@ * @flow */ -import CoreManager from "./CoreManager"; -import encode from "./encode"; -import { continueWhile } from "./promiseUtils"; -import ParseError from "./ParseError"; -import ParseGeoPoint from "./ParseGeoPoint"; -import ParseObject from "./ParseObject"; -import OfflineQuery from "./OfflineQuery"; -import { DEFAULT_PIN } from "./LocalDatastoreUtils"; - -import type LiveQuerySubscription from "./LiveQuerySubscription"; -import type { RequestOptions, FullOptions } from "./RESTController"; +import CoreManager from './CoreManager'; +import encode from './encode'; +import { continueWhile } from './promiseUtils'; +import ParseError from './ParseError'; +import ParseGeoPoint from './ParseGeoPoint'; +import ParseObject from './ParseObject'; +import OfflineQuery from './OfflineQuery'; +import { DEFAULT_PIN } from './LocalDatastoreUtils'; + +import type LiveQuerySubscription from './LiveQuerySubscription'; +import type { RequestOptions, FullOptions } from './RESTController'; type BatchOptions = FullOptions & { batchSize?: number }; @@ -54,7 +54,7 @@ export type QueryJSON = { * @returns {string} */ function quote(s: string): string { - return "\\Q" + s.replace("\\E", "\\E\\\\E\\Q") + "\\E"; + return '\\Q' + s.replace('\\E', '\\E\\\\E\\Q') + '\\E'; } /** @@ -67,13 +67,13 @@ function quote(s: string): string { */ function _getClassNameFromQueries(queries: Array): ?string { let className = null; - queries.forEach((q) => { + queries.forEach(q => { if (!className) { className = q.className; } if (className !== q.className) { - throw new Error("All queries must be for the same class."); + throw new Error('All queries must be for the same class.'); } }); return className; @@ -87,15 +87,15 @@ function _getClassNameFromQueries(queries: Array): ?string { function handleSelectResult(data: any, select: Array) { const serverDataMask = {}; - select.forEach((field) => { - const hasSubObjectSelect = field.indexOf(".") !== -1; + 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; } 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; @@ -104,7 +104,7 @@ function handleSelectResult(data: any, select: Array) { if (obj && !obj.hasOwnProperty(component)) { obj[component] = undefined; } - if (obj && typeof obj === "object") { + if (obj && typeof obj === 'object') { obj = obj[component]; } @@ -144,12 +144,7 @@ function copyMissingDataWithMask(src, dest, mask, copyThisLevel) { } } for (const key in mask) { - if ( - dest[key] !== undefined && - dest[key] !== null && - src !== undefined && - src !== null - ) { + if (dest[key] !== undefined && dest[key] !== null && src !== undefined && src !== null) { //traverse into objects as needed copyMissingDataWithMask(src[key], dest[key], mask[key], true); } @@ -159,17 +154,17 @@ function copyMissingDataWithMask(src, dest, mask, copyThisLevel) { function handleOfflineSort(a, b, sorts) { let order = sorts[0]; const operator = order.slice(0, 1); - const isDescending = operator === "-"; + const isDescending = operator === '-'; if (isDescending) { order = order.substring(1); } - if (order === "_created_at") { - order = "createdAt"; + if (order === '_created_at') { + order = 'createdAt'; } - if (order === "_updated_at") { - order = "updatedAt"; + 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); @@ -257,25 +252,23 @@ class ParseQuery { * @param {(string | Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string. */ constructor(objectClass: string | ParseObject) { - if (typeof objectClass === "string") { - if (objectClass === "User" && CoreManager.get("PERFORM_USER_REWRITE")) { - this.className = "_User"; + if (typeof objectClass === 'string') { + if (objectClass === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { + this.className = '_User'; } else { this.className = objectClass; } } else if (objectClass instanceof ParseObject) { this.className = objectClass.className; - } else if (typeof objectClass === "function") { - if (typeof objectClass.className === "string") { + } else if (typeof objectClass === 'function') { + if (typeof objectClass.className === 'string') { this.className = objectClass.className; } else { const obj = new objectClass(); 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 = {}; @@ -303,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; }); @@ -318,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; }); @@ -333,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; }); @@ -350,7 +343,7 @@ class ParseQuery { * @returns {Parse.Query} */ _addCondition(key: string, condition: string, value: mixed): ParseQuery { - if (!this._where[key] || typeof this._where[key] === "string") { + if (!this._where[key] || typeof this._where[key] === 'string') { this._where[key] = {}; } this._where[key][condition] = encode(value, false, true); @@ -364,15 +357,13 @@ class ParseQuery { * @returns {string} */ _regexStartWith(string: string): string { - return "^" + quote(string); + return '^' + quote(string); } async _handleOfflineQuery(params: any) { OfflineQuery.validateQuery(this); const localDatastore = CoreManager.getLocalDatastore(); - const objects = await localDatastore._serializeObjectsFromPinName( - this._localDatastorePinName - ); + const objects = await localDatastore._serializeObjectsFromPinName(this._localDatastorePinName); let results = objects .map((json, index, arr) => { const object = ParseObject.fromJSON(json, false); @@ -384,20 +375,14 @@ class ParseQuery { } return object; }) - .filter((object) => object !== null); + .filter(object => object !== null); if (params.keys) { - let keys = params.keys.split(","); - const alwaysSelectedKeys = [ - "className", - "objectId", - "createdAt", - "updatedAt", - "ACL", - ]; + 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]; } @@ -406,7 +391,7 @@ class ParseQuery { }); } if (params.order) { - const sorts = params.order.split(","); + const sorts = params.order.split(','); results.sort((a, b) => { return handleOfflineSort(a, b, sorts); }); @@ -431,7 +416,7 @@ class ParseQuery { results = results.splice(0, limit); - if (typeof count === "number") { + if (typeof count === 'number') { return { results, count }; } @@ -449,13 +434,13 @@ class ParseQuery { }; if (this._include.length) { - params.include = this._include.join(","); + params.include = this._include.join(','); } if (this._exclude.length) { - params.excludeKeys = this._exclude.join(","); + params.excludeKeys = this._exclude.join(','); } if (this._select) { - params.keys = this._select.join(","); + params.keys = this._select.join(','); } if (this._count) { params.count = 1; @@ -467,7 +452,7 @@ class ParseQuery { params.skip = this._skip; } if (this._order) { - params.order = this._order.join(","); + params.order = this._order.join(','); } if (this._readPreference) { params.readPreference = this._readPreference; @@ -518,15 +503,15 @@ class ParseQuery { } 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) { @@ -542,7 +527,7 @@ class ParseQuery { } if (json.order) { - this._order = json.order.split(","); + this._order = json.order.split(','); } if (json.readPreference) { @@ -569,18 +554,18 @@ class ParseQuery { if (json.hasOwnProperty(key)) { if ( [ - "where", - "include", - "keys", - "count", - "limit", - "skip", - "order", - "readPreference", - "includeReadPreference", - "subqueryReadPreference", - "hint", - "explain", + 'where', + 'include', + 'keys', + 'count', + 'limit', + 'skip', + 'order', + 'readPreference', + 'includeReadPreference', + 'subqueryReadPreference', + 'hint', + 'explain', ].indexOf(key) === -1 ) { this._extraOptions[key] = json[key]; @@ -622,32 +607,25 @@ class ParseQuery { * the query completes. */ get(objectId: string, options?: FullOptions): Promise { - this.equalTo("objectId", objectId); + this.equalTo('objectId', objectId); const firstOptions = {}; - if (options && options.hasOwnProperty("useMasterKey")) { + if (options && options.hasOwnProperty('useMasterKey')) { firstOptions.useMasterKey = options.useMasterKey; } - if (options && options.hasOwnProperty("sessionToken")) { + if (options && options.hasOwnProperty('sessionToken')) { firstOptions.sessionToken = options.sessionToken; } - if ( - options && - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options && options.hasOwnProperty('context') && typeof options.context === 'object') { 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); }); } @@ -671,16 +649,13 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { findOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { findOptions.context = options.context; } this._setRequestTask(findOptions); @@ -692,39 +667,37 @@ class ParseQuery { if (this._queriesLocalDatastore) { return this._handleOfflineQuery(this.toJSON()); } - return controller - .find(this.className, this.toJSON(), findOptions) - .then((response) => { - // Return generic object when explain is used - if (this._explain) { - return response.results; + 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 => { + // In cases of relations, the server may send back a className + // on the top level of the payload + const override = response.className || this.className; + if (!data.className) { + data.className = override; } - 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; - if (!data.className) { - data.className = override; - } - // Make sure the data object contains keys for all objects that - // have been requested with a select, so that our cached state - // updates correctly. - if (select) { - handleSelectResult(data, select); - } + // Make sure the data object contains keys for all objects that + // have been requested with a select, so that our cached state + // updates correctly. + if (select) { + handleSelectResult(data, select); + } - return ParseObject.fromJSON(data, !select); - }); + return ParseObject.fromJSON(data, !select); + }); - const count = response.count; + const count = response.count; - if (typeof count === "number") { - return { results, count }; - } else { - return results; - } - }); + if (typeof count === 'number') { + return { results, count }; + } else { + return results; + } + }); } /** @@ -767,10 +740,10 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { findOptions.sessionToken = options.sessionToken; } this._setRequestTask(findOptions); @@ -781,11 +754,9 @@ class ParseQuery { params.limit = 0; params.count = 1; - return controller - .find(this.className, params, findOptions) - .then((result) => { - return result.count; - }); + return controller.find(this.className, params, findOptions).then(result => { + return result.count; + }); } /** @@ -806,7 +777,7 @@ class ParseQuery { const distinctOptions = {}; distinctOptions.useMasterKey = true; - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { distinctOptions.sessionToken = options.sessionToken; } this._setRequestTask(distinctOptions); @@ -817,11 +788,9 @@ class ParseQuery { where: this._where, hint: this._hint, }; - return controller - .aggregate(this.className, params, distinctOptions) - .then((results) => { - return results.results; - }); + return controller.aggregate(this.className, params, distinctOptions).then(results => { + return results.results; + }); } /** @@ -840,15 +809,15 @@ class ParseQuery { const aggregateOptions = {}; aggregateOptions.useMasterKey = true; - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { aggregateOptions.sessionToken = options.sessionToken; } this._setRequestTask(aggregateOptions); const controller = CoreManager.getQueryController(); - if (!Array.isArray(pipeline) && typeof pipeline !== "object") { - throw new Error("Invalid pipeline must be Array or Object"); + if (!Array.isArray(pipeline) && typeof pipeline !== 'object') { + throw new Error('Invalid pipeline must be Array or Object'); } if (Object.keys(this._where || {}).length) { @@ -864,11 +833,9 @@ class ParseQuery { explain: this._explain, readPreference: this._readPreference, }; - return controller - .aggregate(this.className, params, aggregateOptions) - .then((results) => { - return results.results; - }); + return controller.aggregate(this.className, params, aggregateOptions).then(results => { + return results.results; + }); } /** @@ -891,16 +858,13 @@ class ParseQuery { options = options || {}; const findOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { findOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { findOptions.context = options.context; } this._setRequestTask(findOptions); @@ -913,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; } @@ -921,26 +885,24 @@ class ParseQuery { }); } - return controller - .find(this.className, params, findOptions) - .then((response) => { - const objects = response.results; - if (!objects[0]) { - return undefined; - } - if (!objects[0].className) { - objects[0].className = this.className; - } + return controller.find(this.className, params, findOptions).then(response => { + const objects = response.results; + if (!objects[0]) { + return undefined; + } + if (!objects[0].className) { + objects[0].className = this.className; + } - // Make sure the data object contains keys for all objects that - // have been requested with a select, so that our cached state - // updates correctly. - if (select) { - handleSelectResult(objects[0], select); - } + // Make sure the data object contains keys for all objects that + // have been requested with a select, so that our cached state + // updates correctly. + if (select) { + handleSelectResult(objects[0], select); + } - return ParseObject.fromJSON(objects[0], !select); - }); + return ParseObject.fromJSON(objects[0], !select); + }); } /** @@ -971,17 +933,17 @@ class ParseQuery { options = options || {}; if (this._order || this._skip || this._limit >= 0) { - const error = "Cannot iterate on a query with sort, skip, or limit."; + 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; }); } @@ -990,10 +952,10 @@ 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") { + } else if (val && typeof val === 'object') { const conditionMap = {}; query._where[attr] = conditionMap; for (const cond in val) { @@ -1004,19 +966,16 @@ class ParseQuery { } } - query.ascending("objectId"); + query.ascending('objectId'); const findOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { findOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("sessionToken")) { + if (options.hasOwnProperty('sessionToken')) { findOptions.sessionToken = options.sessionToken; } - if ( - options.hasOwnProperty("context") && - typeof options.context === "object" - ) { + if (options.hasOwnProperty('context') && typeof options.context === 'object') { findOptions.context = options.context; } @@ -1029,12 +988,10 @@ class ParseQuery { async () => { const [results] = await Promise.all([ query.find(findOptions), - Promise.resolve( - previousResults.length > 0 && callback(previousResults) - ), + Promise.resolve(previousResults.length > 0 && callback(previousResults)), ]); if (results.length >= query._limit) { - query.greaterThan("objectId", results[results.length - 1].id); + query.greaterThan('objectId', results[results.length - 1].id); previousResults = results; } else if (results.length > 0) { await Promise.resolve(callback(results)); @@ -1065,13 +1022,10 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - each( - callback: (obj: ParseObject) => any, - options?: BatchOptions - ): Promise { - return this.eachBatch((results) => { + each(callback: (obj: ParseObject) => any, options?: BatchOptions): Promise { + return this.eachBatch(results => { let callbacksDone = Promise.resolve(); - results.forEach((result) => { + results.forEach(result => { callbacksDone = callbacksDone.then(() => { return callback(result); }); @@ -1087,7 +1041,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ hint(value: mixed): ParseQuery { - if (typeof value === "undefined") { + if (typeof value === 'undefined') { delete this._hint; } this._hint = value; @@ -1101,8 +1055,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ explain(explain: boolean = true): ParseQuery { - if (typeof explain !== "boolean") { - throw new Error("You can only set explain to a boolean value"); + if (typeof explain !== 'boolean') { + throw new Error('You can only set explain to a boolean value'); } this._explain = explain; return this; @@ -1132,17 +1086,13 @@ class ParseQuery { * iteration has completed. */ async map( - callback: ( - currentObject: ParseObject, - index: number, - query: ParseQuery - ) => any, + 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; }); @@ -1174,17 +1124,13 @@ class ParseQuery { * iteration has completed. */ async reduce( - callback: ( - accumulator: any, - currentObject: ParseObject, - index: number - ) => any, + 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) { @@ -1192,19 +1138,15 @@ class ParseQuery { index += 1; return; } - return Promise.resolve(callback(accumulator, object, index)).then( - (result) => { - accumulator = result; - index += 1; - } - ); + return Promise.resolve(callback(accumulator, object, index)).then(result => { + accumulator = result; + index += 1; + }); }, options); 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; } @@ -1233,17 +1175,13 @@ class ParseQuery { * iteration has completed. */ async filter( - callback: ( - currentObject: ParseObject, - index: number, - query: ParseQuery - ) => boolean, + 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); } @@ -1264,11 +1202,11 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ equalTo(key: string | { [key: string]: any }, value: ?mixed): ParseQuery { - if (key && typeof key === "object") { + if (key && typeof key === 'object') { Object.entries(key).forEach(([k, val]) => this.equalTo(k, val)); return this; } - if (typeof value === "undefined") { + if (typeof value === 'undefined') { return this.doesNotExist(key); } @@ -1285,11 +1223,11 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ notEqualTo(key: string | { [key: string]: any }, value: ?mixed): ParseQuery { - if (key && typeof key === "object") { + if (key && typeof key === 'object') { Object.entries(key).forEach(([k, val]) => this.notEqualTo(k, val)); return this; } - return this._addCondition(key, "$ne", value); + return this._addCondition(key, '$ne', value); } /** @@ -1301,7 +1239,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ lessThan(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$lt", value); + return this._addCondition(key, '$lt', value); } /** @@ -1313,7 +1251,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ greaterThan(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$gt", value); + return this._addCondition(key, '$gt', value); } /** @@ -1325,7 +1263,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ lessThanOrEqualTo(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$lte", value); + return this._addCondition(key, '$lte', value); } /** @@ -1337,7 +1275,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ greaterThanOrEqualTo(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$gte", value); + return this._addCondition(key, '$gte', value); } /** @@ -1349,7 +1287,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containedIn(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$in", value); + return this._addCondition(key, '$in', value); } /** @@ -1361,7 +1299,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ notContainedIn(key: string, value: mixed): ParseQuery { - return this._addCondition(key, "$nin", value); + return this._addCondition(key, '$nin', value); } /** @@ -1373,7 +1311,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containedBy(key: string, values: Array): ParseQuery { - return this._addCondition(key, "$containedBy", values); + return this._addCondition(key, '$containedBy', values); } /** @@ -1385,7 +1323,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ containsAll(key: string, values: Array): ParseQuery { - return this._addCondition(key, "$all", values); + return this._addCondition(key, '$all', values); } /** @@ -1402,7 +1340,7 @@ class ParseQuery { values = [values]; } - const regexObject = values.map((value) => { + const regexObject = values.map(value => { return { $regex: _this._regexStartWith(value) }; }); @@ -1416,7 +1354,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ exists(key: string): ParseQuery { - return this._addCondition(key, "$exists", true); + return this._addCondition(key, '$exists', true); } /** @@ -1426,7 +1364,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ doesNotExist(key: string): ParseQuery { - return this._addCondition(key, "$exists", false); + return this._addCondition(key, '$exists', false); } /** @@ -1440,18 +1378,18 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ matches(key: string, regex: RegExp, modifiers: string): ParseQuery { - this._addCondition(key, "$regex", regex); + this._addCondition(key, '$regex', regex); if (!modifiers) { - modifiers = ""; + modifiers = ''; } if (regex.ignoreCase) { - modifiers += "i"; + modifiers += 'i'; } if (regex.multiline) { - modifiers += "m"; + modifiers += 'm'; } if (modifiers.length) { - this._addCondition(key, "$options", modifiers); + this._addCondition(key, '$options', modifiers); } return this; } @@ -1468,7 +1406,7 @@ class ParseQuery { matchesQuery(key: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, "$inQuery", queryJSON); + return this._addCondition(key, '$inQuery', queryJSON); } /** @@ -1483,7 +1421,7 @@ class ParseQuery { doesNotMatchQuery(key: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, "$notInQuery", queryJSON); + return this._addCondition(key, '$notInQuery', queryJSON); } /** @@ -1497,14 +1435,10 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesKeyInQuery( - key: string, - queryKey: string, - query: ParseQuery - ): ParseQuery { + matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, "$select", { + return this._addCondition(key, '$select', { key: queryKey, query: queryJSON, }); @@ -1521,14 +1455,10 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchKeyInQuery( - key: string, - queryKey: string, - query: ParseQuery - ): ParseQuery { + doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { const queryJSON = query.toJSON(); queryJSON.className = query.className; - return this._addCondition(key, "$dontSelect", { + return this._addCondition(key, '$dontSelect', { key: queryKey, query: queryJSON, }); @@ -1543,10 +1473,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ contains(key: string, substring: string): ParseQuery { - if (typeof substring !== "string") { - throw new Error("The value being searched for must be a string."); + if (typeof substring !== 'string') { + throw new Error('The value being searched for must be a string.'); } - return this._addCondition(key, "$regex", quote(substring)); + return this._addCondition(key, '$regex', quote(substring)); } /** @@ -1582,13 +1512,13 @@ class ParseQuery { options = options || {}; if (!key) { - throw new Error("A key is required."); + throw new Error('A key is required.'); } if (!value) { - throw new Error("A search term is required"); + throw new Error('A search term is required'); } - if (typeof value !== "string") { - throw new Error("The value being searched for must be a string."); + if (typeof value !== 'string') { + throw new Error('The value being searched for must be a string.'); } const fullOptions = {}; @@ -1596,13 +1526,13 @@ class ParseQuery { for (const option in options) { switch (option) { - case "language": + case 'language': fullOptions.$language = options[option]; break; - case "caseSensitive": + case 'caseSensitive': fullOptions.$caseSensitive = options[option]; break; - case "diacriticSensitive": + case 'diacriticSensitive': fullOptions.$diacriticSensitive = options[option]; break; default: @@ -1610,7 +1540,7 @@ class ParseQuery { } } - return this._addCondition(key, "$text", { $search: fullOptions }); + return this._addCondition(key, '$text', { $search: fullOptions }); } /** @@ -1619,8 +1549,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ sortByTextScore() { - this.ascending("$score"); - this.select(["$score"]); + this.ascending('$score'); + this.select(['$score']); return this; } @@ -1634,10 +1564,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ startsWith(key: string, prefix: string): ParseQuery { - if (typeof prefix !== "string") { - throw new Error("The value being searched for must be a string."); + if (typeof prefix !== 'string') { + throw new Error('The value being searched for must be a string.'); } - return this._addCondition(key, "$regex", this._regexStartWith(prefix)); + return this._addCondition(key, '$regex', this._regexStartWith(prefix)); } /** @@ -1649,10 +1579,10 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ endsWith(key: string, suffix: string): ParseQuery { - if (typeof suffix !== "string") { - throw new Error("The value being searched for must be a string."); + if (typeof suffix !== 'string') { + throw new Error('The value being searched for must be a string.'); } - return this._addCondition(key, "$regex", quote(suffix) + "$"); + return this._addCondition(key, '$regex', quote(suffix) + '$'); } /** @@ -1668,7 +1598,7 @@ class ParseQuery { // Try to cast it as a GeoPoint point = new ParseGeoPoint(point); } - return this._addCondition(key, "$nearSphere", point); + return this._addCondition(key, '$nearSphere', point); } /** @@ -1691,9 +1621,9 @@ class ParseQuery { ): ParseQuery { if (sorted || sorted === undefined) { this.near(key, point); - return this._addCondition(key, "$maxDistance", maxDistance); + return this._addCondition(key, '$maxDistance', maxDistance); } else { - return this._addCondition(key, "$geoWithin", { + return this._addCondition(key, '$geoWithin', { $centerSphere: [[point.longitude, point.latitude], maxDistance], }); } @@ -1712,12 +1642,7 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinMiles( - key: string, - point: ParseGeoPoint, - maxDistance: number, - sorted: boolean - ): ParseQuery { + withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery { return this.withinRadians(key, point, maxDistance / 3958.8, sorted); } @@ -1755,18 +1680,14 @@ class ParseQuery { * The upper-right inclusive corner of the box. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinGeoBox( - key: string, - southwest: ParseGeoPoint, - northeast: ParseGeoPoint - ): ParseQuery { + withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): ParseQuery { if (!(southwest instanceof ParseGeoPoint)) { southwest = new ParseGeoPoint(southwest); } if (!(northeast instanceof ParseGeoPoint)) { northeast = new ParseGeoPoint(northeast); } - this._addCondition(key, "$within", { $box: [southwest, northeast] }); + this._addCondition(key, '$within', { $box: [southwest, northeast] }); return this; } @@ -1782,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 }); } /** @@ -1794,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 **/ @@ -1823,11 +1744,11 @@ 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(",")); + this._order = this._order.concat(key.replace(/\s/g, '').split(',')); }); return this; @@ -1857,16 +1778,16 @@ 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; + .replace(/\s/g, '') + .split(',') + .map(k => { + return '-' + k; }) ); }); @@ -1885,8 +1806,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ skip(n: number): ParseQuery { - if (typeof n !== "number" || n < 0) { - throw new Error("You can only skip by a positive number"); + if (typeof n !== 'number' || n < 0) { + throw new Error('You can only skip by a positive number'); } this._skip = n; return this; @@ -1899,8 +1820,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ limit(n: number): ParseQuery { - if (typeof n !== "number") { - throw new Error("You can only set the limit to a numeric value"); + if (typeof n !== 'number') { + throw new Error('You can only set the limit to a numeric value'); } this._limit = n; return this; @@ -1916,8 +1837,8 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ withCount(includeCount: boolean = true): ParseQuery { - if (typeof includeCount !== "boolean") { - throw new Error("You can only set withCount to a boolean value"); + if (typeof includeCount !== 'boolean') { + throw new Error('You can only set withCount to a boolean value'); } this._count = includeCount; return this; @@ -1934,7 +1855,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ include(...keys: Array>): ParseQuery { - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { this._include = this._include.concat(key); } else { @@ -1952,7 +1873,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ includeAll(): ParseQuery { - return this.include("*"); + return this.include('*'); } /** @@ -1967,7 +1888,7 @@ class ParseQuery { if (!this._select) { this._select = []; } - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { this._select = this._select.concat(key); } else { @@ -1987,7 +1908,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ exclude(...keys: Array>): ParseQuery { - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { this._exclude = this._exclude.concat(key); } else { @@ -2145,10 +2066,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ cancel(): ParseQuery { - if ( - this._xhrRequest.task && - typeof this._xhrRequest.task.abort === "function" - ) { + if (this._xhrRequest.task && typeof this._xhrRequest.task.abort === 'function') { this._xhrRequest.task._aborted = true; this._xhrRequest.task.abort(); this._xhrRequest.task = null; @@ -2159,7 +2077,7 @@ class ParseQuery { } _setRequestTask(options) { - options.requestTask = (task) => { + options.requestTask = task => { this._xhrRequest.task = task; this._xhrRequest.onchange(); }; @@ -2167,33 +2085,15 @@ class ParseQuery { } const DefaultController = { - find( - className: string, - params: QueryJSON, - options: RequestOptions - ): Promise> { + 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> { + 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); }, }; diff --git a/src/ParseRelation.js b/src/ParseRelation.js index d02ad774a..e467c92c2 100644 --- a/src/ParseRelation.js +++ b/src/ParseRelation.js @@ -9,9 +9,9 @@ * @flow */ -import { RelationOp } from "./ParseOp"; -import ParseObject from "./ParseObject"; -import ParseQuery from "./ParseQuery"; +import { RelationOp } from './ParseOp'; +import ParseObject from './ParseObject'; +import ParseQuery from './ParseQuery'; /** * Creates a new Relation for the given parent object and key. This @@ -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; @@ -85,7 +79,7 @@ class ParseRelation { const change = new RelationOp(objects, []); const parent = this.parent; if (!parent) { - throw new Error("Cannot add to a Relation without a parent"); + throw new Error('Cannot add to a Relation without a parent'); } if (objects.length === 0) { return parent; @@ -107,7 +101,7 @@ class ParseRelation { const change = new RelationOp([], objects); if (!this.parent) { - throw new Error("Cannot remove from a Relation without a parent"); + throw new Error('Cannot remove from a Relation without a parent'); } if (objects.length === 0) { return; @@ -121,9 +115,9 @@ class ParseRelation { * * @returns {object} JSON representation of Relation */ - toJSON(): { __type: "Relation", className: ?string } { + toJSON(): { __type: 'Relation', className: ?string } { return { - __type: "Relation", + __type: 'Relation', className: this.targetClassName, }; } @@ -138,9 +132,7 @@ class ParseRelation { let query; const parent = this.parent; if (!parent) { - throw new Error( - "Cannot construct a query for a Relation without a parent" - ); + throw new Error('Cannot construct a query for a Relation without a parent'); } if (!this.targetClassName) { query = new ParseQuery(parent.className); @@ -148,12 +140,12 @@ class ParseRelation { } else { query = new ParseQuery(this.targetClassName); } - query._addCondition("$relatedTo", "object", { - __type: "Pointer", + query._addCondition('$relatedTo', 'object', { + __type: 'Pointer', className: parent.className, objectId: parent.id, }); - query._addCondition("$relatedTo", "key", this.key); + query._addCondition('$relatedTo', 'key', this.key); return query; } diff --git a/src/ParseRole.js b/src/ParseRole.js index 1ee691b72..07d4c8fa2 100644 --- a/src/ParseRole.js +++ b/src/ParseRole.js @@ -9,12 +9,12 @@ * @flow */ -import ParseACL from "./ParseACL"; -import ParseError from "./ParseError"; -import ParseObject from "./ParseObject"; +import ParseACL from './ParseACL'; +import ParseError from './ParseError'; +import ParseObject from './ParseObject'; -import type { AttributeMap } from "./ObjectStateMutations"; -import type ParseRelation from "./ParseRelation"; +import type { AttributeMap } from './ObjectStateMutations'; +import type ParseRelation from './ParseRelation'; /** * Represents a Role on the Parse server. Roles represent groupings of @@ -37,8 +37,8 @@ class ParseRole extends ParseObject { * cloud. */ constructor(name: string, acl: ParseACL) { - super("_Role"); - if (typeof name === "string" && acl instanceof ParseACL) { + super('_Role'); + if (typeof name === 'string' && acl instanceof ParseACL) { this.setName(name); this.setACL(acl); } @@ -50,11 +50,11 @@ class ParseRole extends ParseObject { * @returns {string} the name of the role. */ getName(): ?string { - const name = this.get("name"); - if (name == null || typeof name === "string") { + const name = this.get('name'); + if (name == null || typeof name === 'string') { return name; } - return ""; + return ''; } /** @@ -75,7 +75,7 @@ class ParseRole extends ParseObject { * @returns {(ParseObject|boolean)} true if the set succeeded. */ setName(name: string, options?: mixed): ParseObject | boolean { - return this.set("name", name, options); + return this.set('name', name, options); } /** @@ -90,7 +90,7 @@ class ParseRole extends ParseObject { * role. */ getUsers(): ParseRelation { - return this.relation("users"); + return this.relation('users'); } /** @@ -105,7 +105,7 @@ class ParseRole extends ParseObject { * role. */ getRoles(): ParseRelation { - return this.relation("roles"); + return this.relation('roles'); } validate(attrs: AttributeMap, options?: mixed): ParseError | boolean { @@ -114,7 +114,7 @@ class ParseRole extends ParseObject { return isInvalid; } - if ("name" in attrs && attrs.name !== this.getName()) { + if ('name' in attrs && attrs.name !== this.getName()) { const newName = attrs.name; if (this.id && this.id !== attrs.objectId) { // Check to see if the objectId being set matches this.id @@ -125,17 +125,13 @@ class ParseRole extends ParseObject { "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." - ); + if (typeof newName !== 'string') { + return new ParseError(ParseError.OTHER_CAUSE, "A role's name must be a String."); } 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.' ); } } @@ -143,6 +139,6 @@ class ParseRole extends ParseObject { } } -ParseObject.registerSubclass("_Role", ParseRole); +ParseObject.registerSubclass('_Role', ParseRole); export default ParseRole; diff --git a/src/ParseSchema.js b/src/ParseSchema.js index 4e89fb47f..6d770e903 100644 --- a/src/ParseSchema.js +++ b/src/ParseSchema.js @@ -9,21 +9,21 @@ * @flow */ -import CoreManager from "./CoreManager"; -import ParseObject from "./ParseObject"; +import CoreManager from './CoreManager'; +import ParseObject from './ParseObject'; const FIELD_TYPES = [ - "String", - "Number", - "Boolean", - "Date", - "File", - "GeoPoint", - "Polygon", - "Array", - "Object", - "Pointer", - "Relation", + 'String', + 'Number', + 'Boolean', + 'Date', + 'File', + 'GeoPoint', + 'Polygon', + 'Array', + 'Object', + 'Pointer', + 'Relation', ]; type FieldOptions = { @@ -58,9 +58,9 @@ class ParseSchema { * @param {string} className Parse Class string. */ constructor(className: string) { - if (typeof className === "string") { - if (className === "User" && CoreManager.get("PERFORM_USER_REWRITE")) { - this.className = "_User"; + if (typeof className === 'string') { + if (className === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { + this.className = '_User'; } else { this.className = className; } @@ -78,9 +78,9 @@ class ParseSchema { */ static all() { const controller = CoreManager.getSchemaController(); - return controller.get("").then((response) => { + return controller.get('').then(response => { if (response.results.length === 0) { - throw new Error("Schema not found."); + throw new Error('Schema not found.'); } return response.results; }); @@ -96,9 +96,9 @@ class ParseSchema { this.assertClassName(); const controller = CoreManager.getSchemaController(); - return controller.get(this.className).then((response) => { + return controller.get(this.className).then(response => { if (!response) { - throw new Error("Schema not found."); + throw new Error('Schema not found.'); } return response; }); @@ -182,7 +182,7 @@ class ParseSchema { */ assertClassName() { if (!this.className) { - throw new Error("You must set a Class Name before making any request."); + throw new Error('You must set a Class Name before making any request.'); } } @@ -211,17 +211,17 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addField(name: string, type: string, options: FieldOptions = {}) { - type = type || "String"; + type = type || 'String'; if (!name) { - throw new Error("field name may not be null."); + throw new Error('field name may not be null.'); } if (FIELD_TYPES.indexOf(type) === -1) { throw new Error(`${type} is not a valid type.`); } const fieldOptions = { type }; - if (typeof options.required === "boolean") { + if (typeof options.required === 'boolean') { fieldOptions.required = options.required; } if (options.defaultValue !== undefined) { @@ -244,10 +244,10 @@ class ParseSchema { */ addIndex(name: string, index: any) { if (!name) { - throw new Error("index name may not be null."); + throw new Error('index name may not be null.'); } if (!index) { - throw new Error("index may not be null."); + throw new Error('index may not be null.'); } this._indexes[name] = index; @@ -263,7 +263,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addString(name: string, options: FieldOptions) { - return this.addField(name, "String", options); + return this.addField(name, 'String', options); } /** @@ -274,7 +274,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addNumber(name: string, options: FieldOptions) { - return this.addField(name, "Number", options); + return this.addField(name, 'Number', options); } /** @@ -285,7 +285,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addBoolean(name: string, options: FieldOptions) { - return this.addField(name, "Boolean", options); + return this.addField(name, 'Boolean', options); } /** @@ -298,11 +298,11 @@ class ParseSchema { addDate(name: string, options: FieldOptions) { if (options && options.defaultValue) { options.defaultValue = { - __type: "Date", + __type: 'Date', iso: new Date(options.defaultValue), }; } - return this.addField(name, "Date", options); + return this.addField(name, 'Date', options); } /** @@ -313,7 +313,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addFile(name: string, options: FieldOptions) { - return this.addField(name, "File", options); + return this.addField(name, 'File', options); } /** @@ -324,7 +324,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addGeoPoint(name: string, options: FieldOptions) { - return this.addField(name, "GeoPoint", options); + return this.addField(name, 'GeoPoint', options); } /** @@ -335,7 +335,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addPolygon(name: string, options: FieldOptions) { - return this.addField(name, "Polygon", options); + return this.addField(name, 'Polygon', options); } /** @@ -346,7 +346,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addArray(name: string, options: FieldOptions) { - return this.addField(name, "Array", options); + return this.addField(name, 'Array', options); } /** @@ -357,7 +357,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ addObject(name: string, options: FieldOptions) { - return this.addField(name, "Object", options); + return this.addField(name, 'Object', options); } /** @@ -370,14 +370,14 @@ class ParseSchema { */ addPointer(name: string, targetClass: string, options: FieldOptions = {}) { if (!name) { - throw new Error("field name may not be null."); + throw new Error('field name may not be null.'); } if (!targetClass) { - throw new Error("You need to set the targetClass of the Pointer."); + throw new Error('You need to set the targetClass of the Pointer.'); } - const fieldOptions = { type: "Pointer", targetClass }; + const fieldOptions = { type: 'Pointer', targetClass }; - if (typeof options.required === "boolean") { + if (typeof options.required === 'boolean') { fieldOptions.required = options.required; } if (options.defaultValue !== undefined) { @@ -399,14 +399,14 @@ class ParseSchema { */ addRelation(name: string, targetClass: string) { if (!name) { - throw new Error("field name may not be null."); + throw new Error('field name may not be null.'); } if (!targetClass) { - throw new Error("You need to set the targetClass of the Relation."); + throw new Error('You need to set the targetClass of the Relation.'); } this._fields[name] = { - type: "Relation", + type: 'Relation', targetClass, }; @@ -420,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; } @@ -431,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; } } @@ -445,29 +445,24 @@ const DefaultController = { }, get(className: string): Promise { - return this.send(className, "GET"); + return this.send(className, 'GET'); }, create(className: string, params: any): Promise { - return this.send(className, "POST", params); + return this.send(className, 'POST', params); }, update(className: string, params: any): Promise { - return this.send(className, "PUT", params); + return this.send(className, 'PUT', params); }, delete(className: string): Promise { - return this.send(className, "DELETE"); + return this.send(className, 'DELETE'); }, purge(className: string): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - "DELETE", - `purge/${className}`, - {}, - { useMasterKey: true } - ); + return RESTController.request('DELETE', `purge/${className}`, {}, { useMasterKey: true }); }, }; diff --git a/src/ParseSession.js b/src/ParseSession.js index 7590e92e7..1b1d8d108 100644 --- a/src/ParseSession.js +++ b/src/ParseSession.js @@ -9,13 +9,13 @@ * @flow */ -import CoreManager from "./CoreManager"; -import isRevocableSession from "./isRevocableSession"; -import ParseObject from "./ParseObject"; -import ParseUser from "./ParseUser"; +import CoreManager from './CoreManager'; +import isRevocableSession from './isRevocableSession'; +import ParseObject from './ParseObject'; +import ParseUser from './ParseUser'; -import type { AttributeMap } from "./ObjectStateMutations"; -import type { RequestOptions, FullOptions } from "./RESTController"; +import type { AttributeMap } from './ObjectStateMutations'; +import type { RequestOptions, FullOptions } from './RESTController'; /** *

A Parse.Session object is a local representation of a revocable session. @@ -30,8 +30,8 @@ class ParseSession extends ParseObject { * @param {object} attributes The initial set of data to store in the user. */ constructor(attributes: ?AttributeMap) { - super("_Session"); - if (attributes && typeof attributes === "object") { + super('_Session'); + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { throw new Error("Can't create an invalid Session"); } @@ -44,22 +44,15 @@ class ParseSession extends ParseObject { * @returns {string} */ getSessionToken(): string { - const token = this.get("sessionToken"); - if (typeof token === "string") { + const token = this.get('sessionToken'); + if (typeof token === 'string') { return token; } - return ""; + return ''; } static readOnlyAttributes() { - return [ - "createdWith", - "expiresAt", - "installationId", - "restricted", - "sessionToken", - "user", - ]; + return ['createdWith', 'expiresAt', 'installationId', 'restricted', 'sessionToken', 'user']; } /** @@ -76,12 +69,12 @@ class ParseSession extends ParseObject { const controller = CoreManager.getSessionController(); const sessionOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + 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."); + return Promise.reject('There is no current user.'); } sessionOptions.sessionToken = user.getSessionToken(); return controller.getSession(sessionOptions); @@ -101,26 +94,24 @@ class ParseSession extends ParseObject { static isCurrentSessionRevocable(): boolean { const currentUser = ParseUser.current(); if (currentUser) { - return isRevocableSession(currentUser.getSessionToken() || ""); + return isRevocableSession(currentUser.getSessionToken() || ''); } return false; } } -ParseObject.registerSubclass("_Session", ParseSession); +ParseObject.registerSubclass('_Session', ParseSession); const DefaultController = { getSession(options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); const session = new ParseSession(); - return RESTController.request("GET", "sessions/me", {}, options).then( - (sessionData) => { - session._finishFetch(sessionData); - session._setExisted(true); - return session; - } - ); + return RESTController.request('GET', 'sessions/me', {}, options).then(sessionData => { + session._finishFetch(sessionData); + session._setExisted(true); + return session; + }); }, }; diff --git a/src/ParseUser.js b/src/ParseUser.js index fd990f48b..65e6444f0 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -9,21 +9,21 @@ * @flow */ -import AnonymousUtils from "./AnonymousUtils"; -import CoreManager from "./CoreManager"; -import isRevocableSession from "./isRevocableSession"; -import ParseError from "./ParseError"; -import ParseObject from "./ParseObject"; -import ParseSession from "./ParseSession"; -import Storage from "./Storage"; +import AnonymousUtils from './AnonymousUtils'; +import CoreManager from './CoreManager'; +import isRevocableSession from './isRevocableSession'; +import ParseError from './ParseError'; +import ParseObject from './ParseObject'; +import ParseSession from './ParseSession'; +import Storage from './Storage'; -import type { AttributeMap } from "./ObjectStateMutations"; -import type { RequestOptions, FullOptions } from "./RESTController"; +import type { AttributeMap } from './ObjectStateMutations'; +import type { RequestOptions, FullOptions } from './RESTController'; export type AuthData = ?{ [key: string]: mixed }; -const CURRENT_USER_KEY = "currentUser"; -let canUseCurrentUser = !CoreManager.get("IS_NODE"); +const CURRENT_USER_KEY = 'currentUser'; +let canUseCurrentUser = !CoreManager.get('IS_NODE'); let currentUserCacheMatchesDisk = false; let currentUserCache = null; @@ -44,8 +44,8 @@ class ParseUser extends ParseObject { * @param {object} attributes The initial set of data to store in the user. */ constructor(attributes: ?AttributeMap) { - super("_User"); - if (attributes && typeof attributes === "object") { + super('_User'); + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { throw new Error("Can't create an invalid Parse User"); } @@ -63,7 +63,7 @@ class ParseUser extends ParseObject { options = options || {}; const upgradeOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { upgradeOptions.useMasterKey = options.useMasterKey; } @@ -91,10 +91,9 @@ class ParseUser extends ParseObject { options: { authData?: AuthData }, saveOpts?: FullOptions = {} ): Promise { - saveOpts.sessionToken = - saveOpts.sessionToken || this.getSessionToken() || ""; + saveOpts.sessionToken = saveOpts.sessionToken || this.getSessionToken() || ''; let authType; - if (typeof provider === "string") { + if (typeof provider === 'string') { authType = provider; if (authProviders[provider]) { provider = authProviders[provider]; @@ -113,10 +112,10 @@ class ParseUser extends ParseObject { } else { authType = provider.getAuthType(); } - if (options && options.hasOwnProperty("authData")) { - const authData = this.get("authData") || {}; - if (typeof authData !== "object") { - throw new Error("Invalid type: authData field should be an object"); + if (options && options.hasOwnProperty('authData')) { + const authData = this.get('authData') || {}; + if (typeof authData !== 'object') { + throw new Error('Invalid type: authData field should be an object'); } authData[authType] = options.authData; @@ -132,7 +131,7 @@ class ParseUser extends ParseObject { () => { resolve(this); }, - (error) => { + error => { reject(error); } ); @@ -171,14 +170,14 @@ class ParseUser extends ParseObject { return; } let authType; - if (typeof provider === "string") { + if (typeof provider === 'string') { authType = provider; provider = authProviders[authType]; } else { authType = provider.getAuthType(); } - const authData = this.get("authData"); - if (!provider || !authData || typeof authData !== "object") { + const authData = this.get('authData'); + if (!provider || !authData || typeof authData !== 'object') { return; } const success = provider.restoreAuthentication(authData[authType]); @@ -191,8 +190,8 @@ class ParseUser extends ParseObject { * Synchronizes authData for all providers. */ _synchronizeAllAuthData() { - const authData = this.get("authData"); - if (typeof authData !== "object") { + const authData = this.get('authData'); + if (typeof authData !== 'object') { return; } @@ -208,8 +207,8 @@ class ParseUser extends ParseObject { if (!this.isCurrent()) { return; } - const authData = this.get("authData"); - if (typeof authData !== "object") { + const authData = this.get('authData'); + if (typeof authData !== 'object') { return; } @@ -243,13 +242,13 @@ class ParseUser extends ParseObject { */ _isLinked(provider: any): boolean { let authType; - if (typeof provider === "string") { + if (typeof provider === 'string') { authType = provider; } else { authType = provider.getAuthType(); } - const authData = this.get("authData") || {}; - if (typeof authData !== "object") { + const authData = this.get('authData') || {}; + if (typeof authData !== 'object') { return false; } return !!authData[authType]; @@ -259,8 +258,8 @@ class ParseUser extends ParseObject { * Deauthenticates all providers. */ _logOutWithAll() { - const authData = this.get("authData"); - if (typeof authData !== "object") { + const authData = this.get('authData'); + if (typeof authData !== 'object') { return; } @@ -279,7 +278,7 @@ class ParseUser extends ParseObject { if (!this.isCurrent()) { return; } - if (typeof provider === "string") { + if (typeof provider === 'string') { provider = authProviders[provider]; } if (provider && provider.deauthenticate) { @@ -295,7 +294,7 @@ class ParseUser extends ParseObject { */ _preserveFieldsOnFetch(): AttributeMap { return { - sessionToken: this.get("sessionToken"), + sessionToken: this.get('sessionToken'), }; } @@ -315,11 +314,11 @@ class ParseUser extends ParseObject { * @returns {string} */ getUsername(): ?string { - const username = this.get("username"); - if (username == null || typeof username === "string") { + const username = this.get('username'); + if (username == null || typeof username === 'string') { return username; } - return ""; + return ''; } /** @@ -330,16 +329,12 @@ class ParseUser extends ParseObject { setUsername(username: string) { // Strip anonymity, even we do not support anonymous user in js SDK, we may // encounter anonymous user created by android/iOS in cloud code. - const authData = this.get("authData"); - if ( - authData && - typeof authData === "object" && - authData.hasOwnProperty("anonymous") - ) { + const authData = this.get('authData'); + if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) { // We need to set anonymous to null instead of deleting it in order to remove it from Parse. authData.anonymous = null; } - this.set("username", username); + this.set('username', username); } /** @@ -348,7 +343,7 @@ class ParseUser extends ParseObject { * @param {string} password User's Password */ setPassword(password: string) { - this.set("password", password); + this.set('password', password); } /** @@ -357,11 +352,11 @@ class ParseUser extends ParseObject { * @returns {string} User's Email */ getEmail(): ?string { - const email = this.get("email"); - if (email == null || typeof email === "string") { + const email = this.get('email'); + if (email == null || typeof email === 'string') { return email; } - return ""; + return ''; } /** @@ -371,7 +366,7 @@ class ParseUser extends ParseObject { * @returns {boolean} */ setEmail(email: string) { - return this.set("email", email); + return this.set('email', email); } /** @@ -382,11 +377,11 @@ class ParseUser extends ParseObject { * @returns {string} the session token, or undefined */ getSessionToken(): ?string { - const token = this.get("sessionToken"); - if (token == null || typeof token === "string") { + const token = this.get('sessionToken'); + if (token == null || typeof token === 'string') { return token; } - return ""; + return ''; } /** @@ -396,7 +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; } /** @@ -416,10 +411,10 @@ class ParseUser extends ParseObject { options = options || {}; const signupOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { signupOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("installationId")) { + if (options.hasOwnProperty('installationId')) { signupOptions.installationId = options.installationId; } @@ -442,13 +437,13 @@ class ParseUser extends ParseObject { options = options || {}; const loginOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { loginOptions.useMasterKey = options.useMasterKey; } - if (options.hasOwnProperty("installationId")) { + if (options.hasOwnProperty('installationId')) { loginOptions.installationId = options.installationId; } - if (options.hasOwnProperty("usePost")) { + if (options.hasOwnProperty('usePost')) { loginOptions.usePost = options.usePost; } @@ -528,17 +523,14 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with a user * when the password is correct. */ - verifyPassword( - password: string, - options?: RequestOptions - ): Promise { - const username = this.getUsername() || ""; + verifyPassword(password: string, options?: RequestOptions): Promise { + const username = this.getUsername() || ''; return ParseUser.verifyPassword(username, password, options); } static readOnlyAttributes() { - return ["sessionToken"]; + return ['sessionToken']; } /** @@ -549,13 +541,10 @@ 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") { + if (prop !== 'className') { Object.defineProperty(ParseUser.prototype, prop, { value: protoProps[prop], enumerable: false, @@ -568,7 +557,7 @@ class ParseUser extends ParseObject { if (classProps) { for (const prop in classProps) { - if (prop !== "className") { + if (prop !== 'className') { Object.defineProperty(ParseUser, prop, { value: classProps[prop], enumerable: false, @@ -626,12 +615,7 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the signup completes. */ - static signUp( - username: string, - password: string, - attrs: AttributeMap, - options?: FullOptions - ) { + static signUp(username: string, password: string, attrs: AttributeMap, options?: FullOptions) { attrs = attrs || {}; attrs.username = username; attrs.password = password; @@ -652,14 +636,10 @@ class ParseUser extends ParseObject { * the login completes. */ 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.") - ); - } else if (typeof password !== "string") { - return Promise.reject( - new ParseError(ParseError.OTHER_CAUSE, "Password must be a string.") - ); + if (typeof username !== '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.')); } const user = new this(); user._finishFetch({ username: username, password: password }); @@ -679,16 +659,14 @@ 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, }; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { becomeOptions.useMasterKey = options.useMasterKey; } @@ -781,7 +759,7 @@ class ParseUser extends ParseObject { options = options || {}; const requestOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { requestOptions.useMasterKey = options.useMasterKey; } @@ -802,7 +780,7 @@ class ParseUser extends ParseObject { options = options || {}; const requestOptions = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { requestOptions.useMasterKey = options.useMasterKey; } @@ -820,27 +798,19 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with a user * when the password is correct. */ - 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.") - ); + 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.')); } - if (typeof password !== "string") { - return Promise.reject( - new ParseError(ParseError.OTHER_CAUSE, "Password must be a string.") - ); + if (typeof password !== 'string') { + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } options = options || {}; const verificationOption = {}; - if (options.hasOwnProperty("useMasterKey")) { + if (options.hasOwnProperty('useMasterKey')) { verificationOption.useMasterKey = options.useMasterKey; } @@ -858,7 +828,7 @@ class ParseUser extends ParseObject { * @static */ static allowCustomUserClass(isAllowed: boolean) { - CoreManager.set("PERFORM_USER_REWRITE", !isAllowed); + CoreManager.set('PERFORM_USER_REWRITE', !isAllowed); } /** @@ -877,7 +847,7 @@ class ParseUser extends ParseObject { */ static enableRevocableSession(options?: RequestOptions) { options = options || {}; - CoreManager.set("FORCE_REVOCABLE_SESSION", true); + CoreManager.set('FORCE_REVOCABLE_SESSION', true); if (canUseCurrentUser) { const current = ParseUser.current(); if (current) { @@ -924,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()); } @@ -939,11 +909,7 @@ class ParseUser extends ParseObject { * @static * @returns {Promise} */ - static _logInWith( - provider: any, - options: { authData?: AuthData }, - saveOpts?: FullOptions - ) { + static _logInWith(provider: any, options: { authData?: AuthData }, saveOpts?: FullOptions) { const user = new this(); return user.linkWith(provider, options, saveOpts); } @@ -958,7 +924,7 @@ class ParseUser extends ParseObject { } } -ParseObject.registerSubclass("_User", ParseUser); +ParseObject.registerSubclass('_User', ParseUser); const DefaultController = { updateUserOnDisk(user) { @@ -966,11 +932,11 @@ const DefaultController = { const json = user.toJSON(); delete json.password; - json.className = "_User"; + json.className = '_User'; let userData = JSON.stringify(json); - if (CoreManager.get("ENCRYPTED_USER")) { + 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 user; @@ -986,11 +952,7 @@ const DefaultController = { async setCurrentUser(user) { const currentUser = await this.currentUserAsync(); - if ( - currentUser && - !user.equals(currentUser) && - AnonymousUtils.isLinked(currentUser) - ) { + if (currentUser && !user.equals(currentUser) && AnonymousUtils.isLinked(currentUser)) { await currentUser.destroy({ sessionToken: currentUser.getSessionToken(), }); @@ -1010,8 +972,8 @@ const DefaultController = { } if (Storage.async()) { throw new Error( - "Cannot call currentUser() when using a platform with an async " + - "storage system. Call currentUserAsync() instead." + 'Cannot call currentUser() when using a platform with an async ' + + 'storage system. Call currentUserAsync() instead.' ); } const path = Storage.generatePath(CURRENT_USER_KEY); @@ -1021,13 +983,13 @@ const DefaultController = { currentUserCache = null; return null; } - if (CoreManager.get("ENCRYPTED_USER")) { + if (CoreManager.get('ENCRYPTED_USER')) { const crypto = CoreManager.getCryptoController(); - userData = crypto.decrypt(userData, CoreManager.get("ENCRYPTED_KEY")); + userData = crypto.decrypt(userData, CoreManager.get('ENCRYPTED_KEY')); } userData = JSON.parse(userData); if (!userData.className) { - userData.className = "_User"; + userData.className = '_User'; } if (userData._id) { if (userData.objectId !== userData._id) { @@ -1053,22 +1015,19 @@ const DefaultController = { 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; return Promise.resolve(null); } - if (CoreManager.get("ENCRYPTED_USER")) { + if (CoreManager.get('ENCRYPTED_USER')) { const crypto = CoreManager.getCryptoController(); - userData = crypto.decrypt( - userData.toString(), - CoreManager.get("ENCRYPTED_KEY") - ); + userData = crypto.decrypt(userData.toString(), CoreManager.get('ENCRYPTED_KEY')); } userData = JSON.parse(userData); if (!userData.className) { - userData.className = "_User"; + userData.className = '_User'; } if (userData._id) { if (userData.objectId !== userData._id) { @@ -1087,28 +1046,18 @@ const DefaultController = { }); }, - signUp( - user: ParseUser, - attrs: AttributeMap, - options: RequestOptions - ): Promise { - const username = (attrs && attrs.username) || user.get("username"); - const password = (attrs && attrs.password) || user.get("password"); + signUp(user: ParseUser, attrs: AttributeMap, options: RequestOptions): Promise { + const username = (attrs && attrs.username) || user.get('username'); + const password = (attrs && attrs.password) || user.get('password'); 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.') ); } @@ -1127,46 +1076,33 @@ const DefaultController = { const RESTController = CoreManager.getRESTController(); const stateController = CoreManager.getObjectStateController(); const auth = { - username: user.get("username"), - password: user.get("password"), + username: user.get('username'), + 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) => { - user._finishFetch(response); - user._setExisted(true); - return DefaultController.setCurrentUser(user); - } - ); + return RESTController.request('GET', 'users/me', {}, options).then(response => { + user._finishFetch(response); + user._setExisted(true); + return DefaultController.setCurrentUser(user); + }); }, hydrate(user: ParseUser, userJSON: AttributeMap): Promise { @@ -1181,21 +1117,19 @@ const DefaultController = { me(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request("GET", "users/me", {}, options).then( - (response) => { - user._finishFetch(response); - user._setExisted(true); - return user; - } - ); + return RESTController.request('GET', 'users/me', {}, options).then(response => { + user._finishFetch(response); + user._setExisted(true); + return user; + }); }, 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) { @@ -1209,12 +1143,7 @@ const DefaultController = { } }) .then(() => { - return RESTController.request( - "POST", - "logout", - {}, - { sessionToken: currentSession } - ); + return RESTController.request('POST', 'logout', {}, { sessionToken: currentSession }); }); } currentUser._logOutWithAll(); @@ -1229,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() }); @@ -1278,22 +1194,12 @@ 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); }, }; diff --git a/src/Push.js b/src/Push.js index 608bd04ce..dcfec330d 100644 --- a/src/Push.js +++ b/src/Push.js @@ -9,10 +9,10 @@ * @flow */ -import CoreManager from "./CoreManager"; -import ParseQuery from "./ParseQuery"; +import CoreManager from './CoreManager'; +import ParseQuery from './ParseQuery'; -import type { WhereClause } from "./ParseQuery"; +import type { WhereClause } from './ParseQuery'; export type PushData = { where?: WhereClause | ParseQuery, @@ -57,18 +57,16 @@ export function send(data: PushData): Promise { data.where = data.where.toJSON().where; } - if (data.push_time && typeof data.push_time === "object") { + if (data.push_time && typeof data.push_time === 'object') { data.push_time = data.push_time.toJSON(); } - if (data.expiration_time && typeof data.expiration_time === "object") { + if (data.expiration_time && typeof data.expiration_time === 'object') { data.expiration_time = data.expiration_time.toJSON(); } 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,7 +74,7 @@ export function send(data: PushData): Promise { const DefaultController = { send(data: PushData) { - return CoreManager.getRESTController().request("POST", "push", data, { + return CoreManager.getRESTController().request('POST', 'push', data, { useMasterKey: true, }); }, diff --git a/src/RESTController.js b/src/RESTController.js index 7669e7e38..292cf9027 100644 --- a/src/RESTController.js +++ b/src/RESTController.js @@ -9,11 +9,11 @@ * @flow */ /* global XMLHttpRequest, XDomainRequest */ -const uuidv4 = require("uuid/v4"); +const uuidv4 = require('uuid/v4'); -import CoreManager from "./CoreManager"; -import ParseError from "./ParseError"; -import { resolvingPromise } from "./promiseUtils"; +import CoreManager from './CoreManager'; +import ParseError from './ParseError'; +import { resolvingPromise } from './promiseUtils'; export type RequestOptions = { useMasterKey?: boolean, @@ -38,31 +38,22 @@ export type FullOptions = { }; let XHR = null; -if (typeof XMLHttpRequest !== "undefined") { +if (typeof XMLHttpRequest !== 'undefined') { XHR = XMLHttpRequest; } -if (process.env.PARSE_BUILD === "node") { - XHR = require("xmlhttprequest").XMLHttpRequest; +if (process.env.PARSE_BUILD === 'node') { + XHR = require('xmlhttprequest').XMLHttpRequest; } -if (process.env.PARSE_BUILD === "weapp") { - XHR = require("./Xhr.weapp"); +if (process.env.PARSE_BUILD === 'weapp') { + XHR = require('./Xhr.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 -) { +function ajaxIE9(method: string, url: string, data: any, headers?: any, options?: FullOptions) { return new Promise((resolve, reject) => { const xdr = new XDomainRequest(); xdr.onload = function () { @@ -87,40 +78,31 @@ function ajaxIE9( reject(fakeResponse); }; xdr.onprogress = function () { - if (options && typeof options.progress === "function") { + if (options && typeof options.progress === 'function') { options.progress(xdr.responseText); } }; xdr.open(method, url); xdr.send(data); - if (options && typeof options.requestTask === "function") { + if (options && typeof options.requestTask === 'function') { options.requestTask(xdr); } }); } const RESTController = { - ajax( - method: string, - url: string, - data: any, - headers?: any, - options?: FullOptions - ) { + ajax(method: string, url: string, data: any, headers?: any, options?: FullOptions) { if (useXDomainRequest) { return ajaxIE9(method, url, data, headers, options); } const promise = resolvingPromise(); - const isIdempotent = - CoreManager.get("IDEMPOTENCY") && ["POST", "PUT"].includes(method); - const requestId = isIdempotent ? uuidv4() : ""; + const isIdempotent = CoreManager.get('IDEMPOTENCY') && ['POST', 'PUT'].includes(method); + const requestId = isIdempotent ? uuidv4() : ''; let attempts = 0; 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; @@ -136,13 +118,9 @@ const RESTController = { try { response = JSON.parse(xhr.responseText); - if (typeof xhr.getResponseHeader === "function") { - if ( - (xhr.getAllResponseHeaders() || "").includes( - "x-parse-job-status-id: " - ) - ) { - response = xhr.getResponseHeader("x-parse-job-status-id"); + if (typeof xhr.getResponseHeader === 'function') { + if ((xhr.getAllResponseHeaders() || '').includes('x-parse-job-status-id: ')) { + response = xhr.getResponseHeader('x-parse-job-status-id'); } } } catch (e) { @@ -153,14 +131,12 @@ const RESTController = { } } else if (xhr.status >= 500 || xhr.status === 0) { // retry on 5XX or node-xmlhttprequest error - if (++attempts < CoreManager.get("REQUEST_ATTEMPT_LIMIT")) { + 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"); + promise.reject('Unable to connect to the Parse API'); } else { // After the retry limit is reached, fail promise.reject(xhr); @@ -171,56 +147,42 @@ const RESTController = { }; headers = headers || {}; - if (typeof headers["Content-Type"] !== "string") { - headers["Content-Type"] = "text/plain"; // Avoid pre-flight + 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 + - ")"; + if (CoreManager.get('IS_NODE')) { + headers['User-Agent'] = + 'Parse/' + CoreManager.get('VERSION') + ' (NodeJS ' + process.versions.node + ')'; } if (isIdempotent) { - headers["X-Parse-Request-Id"] = requestId; + 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"); + if (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"); + const customHeaders = CoreManager.get('REQUEST_HEADERS'); for (const key in customHeaders) { headers[key] = customHeaders[key]; } function handleProgress(type, event) { - if (options && typeof options.progress === "function") { + 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) => { - handleProgress("download", event); + xhr.onprogress = event => { + handleProgress('download', event); }; if (xhr.upload) { - xhr.upload.onprogress = (event) => { - handleProgress("upload", event); + xhr.upload.onprogress = event => { + handleProgress('upload', event); }; } @@ -238,7 +200,7 @@ const RESTController = { }; xhr.send(data); - if (options && typeof options.requestTask === "function") { + if (options && typeof options.requestTask === 'function') { options.requestTask(xhr); } }; @@ -249,14 +211,14 @@ const RESTController = { request(method: string, path: string, data: mixed, options?: RequestOptions) { options = options || {}; - let url = CoreManager.get("SERVER_URL"); - if (url[url.length - 1] !== "/") { - url += "/"; + let url = CoreManager.get('SERVER_URL'); + if (url[url.length - 1] !== '/') { + url += '/'; } url += path; const payload = {}; - if (data && typeof data === "object") { + if (data && typeof data === 'object') { for (const k in data) { payload[k] = data[k]; } @@ -268,38 +230,38 @@ const RESTController = { payload._context = context; } - if (method !== "POST") { + if (method !== 'POST') { payload._method = method; - method = "POST"; + method = 'POST'; } - payload._ApplicationId = CoreManager.get("APPLICATION_ID"); - const jsKey = CoreManager.get("JAVASCRIPT_KEY"); + payload._ApplicationId = CoreManager.get('APPLICATION_ID'); + const jsKey = CoreManager.get('JAVASCRIPT_KEY'); if (jsKey) { payload._JavaScriptKey = jsKey; } - payload._ClientVersion = CoreManager.get("VERSION"); + payload._ClientVersion = CoreManager.get('VERSION'); let useMasterKey = options.useMasterKey; - if (typeof useMasterKey === "undefined") { - useMasterKey = CoreManager.get("USE_MASTER_KEY"); + if (typeof useMasterKey === 'undefined') { + useMasterKey = CoreManager.get('USE_MASTER_KEY'); } if (useMasterKey) { - if (CoreManager.get("MASTER_KEY")) { + if (CoreManager.get('MASTER_KEY')) { delete payload._JavaScriptKey; - payload._MasterKey = CoreManager.get("MASTER_KEY"); + payload._MasterKey = CoreManager.get('MASTER_KEY'); } else { - throw new Error("Cannot use the Master Key, it has not been provided."); + throw new Error('Cannot use the Master Key, it has not been provided.'); } } - if (CoreManager.get("FORCE_REVOCABLE_SESSION")) { - payload._RevocableSession = "1"; + if (CoreManager.get('FORCE_REVOCABLE_SESSION')) { + payload._RevocableSession = '1'; } const installationId = options.installationId; let installationIdPromise; - if (installationId && typeof installationId === "string") { + if (installationId && typeof installationId === 'string') { installationIdPromise = Promise.resolve(installationId); } else { const installationController = CoreManager.getInstallationController(); @@ -307,13 +269,13 @@ const RESTController = { } return installationIdPromise - .then((iid) => { + .then(iid => { payload._InstallationId = iid; const userController = CoreManager.getUserController(); - if (options && typeof options.sessionToken === "string") { + if (options && typeof options.sessionToken === 'string') { return Promise.resolve(options.sessionToken); } else if (userController) { - return userController.currentUserAsync().then((user) => { + return userController.currentUserAsync().then(user => { if (user) { return Promise.resolve(user.getSessionToken()); } @@ -322,25 +284,21 @@ const RESTController = { } return Promise.resolve(null); }) - .then((token) => { + .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 RESTController.ajax(method, url, payloadString, {}, options).then( + ({ response, status }) => { + if (options.returnStatus) { + return { ...response, _status: status }; + } else { + return response; + } } - }); + ); }) .catch(RESTController.handleError); }, @@ -357,15 +315,14 @@ 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 { const message = response.message ? response.message : response; error = new ParseError( ParseError.CONNECTION_FAILED, - "XMLHttpRequest failed: " + JSON.stringify(message) + 'XMLHttpRequest failed: ' + JSON.stringify(message) ); } return Promise.reject(error); diff --git a/src/SingleInstanceStateController.js b/src/SingleInstanceStateController.js index 569d38993..5ef86c442 100644 --- a/src/SingleInstanceStateController.js +++ b/src/SingleInstanceStateController.js @@ -9,15 +9,10 @@ * @flow */ -import * as ObjectStateMutations from "./ObjectStateMutations"; +import * as ObjectStateMutations from './ObjectStateMutations'; -import type { Op } from "./ParseOp"; -import type { - AttributeMap, - ObjectCache, - OpsMap, - State, -} from "./ObjectStateMutations"; +import type { Op } from './ParseOp'; +import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; type ObjectIdentifier = { className: string, @@ -126,30 +121,15 @@ export function estimateAttribute(obj: ObjectIdentifier, attr: string): mixed { export function estimateAttributes(obj: ObjectIdentifier): AttributeMap { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttributes( - serverData, - pendingOps, - obj.className, - obj.id - ); + return ObjectStateMutations.estimateAttributes(serverData, pendingOps, obj.className, obj.id); } -export function commitServerChanges( - obj: ObjectIdentifier, - changes: AttributeMap -) { +export function commitServerChanges(obj: ObjectIdentifier, changes: AttributeMap) { const state = initializeState(obj); - ObjectStateMutations.commitServerChanges( - state.serverData, - state.objectCache, - changes - ); + ObjectStateMutations.commitServerChanges(state.serverData, state.objectCache, changes); } -export function enqueueTask( - obj: ObjectIdentifier, - task: () => Promise -): Promise { +export function enqueueTask(obj: ObjectIdentifier, task: () => Promise): Promise { const state = initializeState(obj); return state.tasks.enqueue(task); } diff --git a/src/Socket.weapp.js b/src/Socket.weapp.js index 9336bbd53..35affd6f3 100644 --- a/src/Socket.weapp.js +++ b/src/Socket.weapp.js @@ -9,7 +9,7 @@ module.exports = class SocketWeapp { 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); }); diff --git a/src/Storage.js b/src/Storage.js index 05c3553a9..0f2806145 100644 --- a/src/Storage.js +++ b/src/Storage.js @@ -9,7 +9,7 @@ * @flow */ -import CoreManager from "./CoreManager"; +import CoreManager from './CoreManager'; const Storage = { async(): boolean { @@ -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(); }, @@ -90,21 +82,21 @@ const Storage = { }, generatePath(path: string): string { - if (!CoreManager.get("APPLICATION_ID")) { - throw new Error("You need to call Parse.initialize before using Parse."); + if (!CoreManager.get('APPLICATION_ID')) { + throw new Error('You need to call Parse.initialize before using Parse.'); } - if (typeof path !== "string") { - throw new Error("Tried to get a Storage path that was not a String."); + if (typeof path !== 'string') { + throw new Error('Tried to get a Storage path that was not a String.'); } - if (path[0] === "/") { + if (path[0] === '/') { path = path.substr(1); } - return "Parse/" + CoreManager.get("APPLICATION_ID") + "/" + path; + return 'Parse/' + CoreManager.get('APPLICATION_ID') + '/' + path; }, _clear() { const controller = CoreManager.getStorageController(); - if (controller.hasOwnProperty("clear")) { + if (controller.hasOwnProperty('clear')) { controller.clear(); } }, @@ -112,12 +104,12 @@ const Storage = { module.exports = Storage; -if (process.env.PARSE_BUILD === "react-native") { - CoreManager.setStorageController(require("./StorageController.react-native")); -} else if (process.env.PARSE_BUILD === "browser") { - CoreManager.setStorageController(require("./StorageController.browser")); -} else if (process.env.PARSE_BUILD === "weapp") { - CoreManager.setStorageController(require("./StorageController.weapp")); +if (process.env.PARSE_BUILD === 'react-native') { + CoreManager.setStorageController(require('./StorageController.react-native')); +} else if (process.env.PARSE_BUILD === 'browser') { + CoreManager.setStorageController(require('./StorageController.browser')); +} else if (process.env.PARSE_BUILD === 'weapp') { + CoreManager.setStorageController(require('./StorageController.weapp')); } else { - CoreManager.setStorageController(require("./StorageController.default")); + CoreManager.setStorageController(require('./StorageController.default')); } diff --git a/src/StorageController.react-native.js b/src/StorageController.react-native.js index 51dd29588..b6b8443c2 100644 --- a/src/StorageController.react-native.js +++ b/src/StorageController.react-native.js @@ -10,7 +10,7 @@ * @private */ -import CoreManager from "./CoreManager"; +import CoreManager from './CoreManager'; const StorageController = { async: 1, diff --git a/src/TaskQueue.js b/src/TaskQueue.js index 5020c5488..58d4df297 100644 --- a/src/TaskQueue.js +++ b/src/TaskQueue.js @@ -8,7 +8,7 @@ * * @flow */ -import { resolvingPromise } from "./promiseUtils"; +import { resolvingPromise } from './promiseUtils'; type Task = { task: () => Promise, @@ -34,7 +34,7 @@ class TaskQueue { this._dequeue(); taskComplete.resolve(); }, - (error) => { + error => { this._dequeue(); taskComplete.reject(error); } @@ -52,7 +52,7 @@ class TaskQueue { this._dequeue(); next._completion.resolve(); }, - (error) => { + error => { this._dequeue(); next._completion.reject(error); } diff --git a/src/UniqueInstanceStateController.js b/src/UniqueInstanceStateController.js index 93cf6676d..8ecbcee9b 100644 --- a/src/UniqueInstanceStateController.js +++ b/src/UniqueInstanceStateController.js @@ -9,17 +9,12 @@ * @flow */ -import * as ObjectStateMutations from "./ObjectStateMutations"; -import TaskQueue from "./TaskQueue"; - -import type { Op } from "./ParseOp"; -import type ParseObject from "./ParseObject"; -import type { - AttributeMap, - ObjectCache, - OpsMap, - State, -} from "./ObjectStateMutations"; +import * as ObjectStateMutations from './ObjectStateMutations'; +import TaskQueue from './TaskQueue'; + +import type { Op } from './ParseOp'; +import type ParseObject from './ParseObject'; +import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; let objectState = new WeakMap(); @@ -120,21 +115,12 @@ export function estimateAttribute(obj: ParseObject, attr: string): mixed { export function estimateAttributes(obj: ParseObject): AttributeMap { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttributes( - serverData, - pendingOps, - obj.className, - obj.id - ); + return ObjectStateMutations.estimateAttributes(serverData, pendingOps, obj.className, obj.id); } export function commitServerChanges(obj: ParseObject, changes: AttributeMap) { const state = initializeState(obj); - ObjectStateMutations.commitServerChanges( - state.serverData, - state.objectCache, - changes - ); + ObjectStateMutations.commitServerChanges(state.serverData, state.objectCache, changes); } export function enqueueTask(obj: ParseObject, task: () => Promise): Promise { diff --git a/src/Xhr.weapp.js b/src/Xhr.weapp.js index d706ca0f6..cb9f90121 100644 --- a/src/Xhr.weapp.js +++ b/src/Xhr.weapp.js @@ -9,12 +9,12 @@ module.exports = class XhrWeapp { this.header = {}; this.readyState = this.DONE; this.status = 0; - this.response = ""; - this.responseType = ""; - this.responseText = ""; + this.response = ''; + this.responseType = ''; + this.responseText = ''; this.responseHeader = {}; - this.method = ""; - this.url = ""; + this.method = ''; + this.url = ''; this.onabort = () => {}; this.onprogress = () => {}; this.onerror = () => {}; @@ -23,9 +23,9 @@ module.exports = class XhrWeapp { } getAllResponseHeaders() { - let header = ""; + let header = ''; for (const key in this.responseHeader) { - header += key + ":" + this.getResponseHeader(key) + "\r\n"; + 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,12 +69,12 @@ 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, loaded: res.totalBytesWritten, diff --git a/src/__tests__/Analytics-test.js b/src/__tests__/Analytics-test.js index 56142a91b..8c1845c1c 100644 --- a/src/__tests__/Analytics-test.js +++ b/src/__tests__/Analytics-test.js @@ -7,71 +7,58 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../Analytics"); -jest.dontMock("../CoreManager"); +jest.dontMock('../Analytics'); +jest.dontMock('../CoreManager'); -const Analytics = require("../Analytics"); -const CoreManager = require("../CoreManager"); +const Analytics = require('../Analytics'); +const CoreManager = require('../CoreManager'); const defaultController = CoreManager.getAnalyticsController(); -describe("Analytics", () => { +describe('Analytics', () => { beforeEach(() => { const track = jest.fn(); track.mockReturnValue(Promise.resolve()); CoreManager.setAnalyticsController({ track: track }); }); - it("throws when no event name is provided", () => { - expect(Analytics.track).toThrow( - "A name for the custom event must be provided" - ); + it('throws when no event name is 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", - {}, - ]); + it('trims whitespace from event names', () => { + Analytics.track(' before', {}); + expect(CoreManager.getAnalyticsController().track.mock.calls[0]).toEqual(['before', {}]); - Analytics.track("after ", {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[1]).toEqual([ - "after", - {}, - ]); + Analytics.track('after ', {}); + expect(CoreManager.getAnalyticsController().track.mock.calls[1]).toEqual(['after', {}]); - Analytics.track(" both ", {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[2]).toEqual([ - "both", - {}, - ]); + Analytics.track(' both ', {}); + expect(CoreManager.getAnalyticsController().track.mock.calls[2]).toEqual(['both', {}]); }); - it("passes along event names and dimensions", () => { - Analytics.track("myEvent", { value: "a" }); + it('passes along event names and dimensions', () => { + Analytics.track('myEvent', { value: 'a' }); expect(CoreManager.getAnalyticsController().track.mock.calls[0]).toEqual([ - "myEvent", - { value: "a" }, + 'myEvent', + { value: 'a' }, ]); }); - it("throws when invalid dimensions are provided", () => { - expect(Analytics.track.bind(null, "event", { number: 12 })).toThrow( + 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", { null: null })).toThrow( + expect(Analytics.track.bind(null, 'event', { null: null })).toThrow( 'track() dimensions expects keys and values of type "string".' ); }); }); -describe("AnalyticsController", () => { +describe('AnalyticsController', () => { beforeEach(() => { CoreManager.setAnalyticsController(defaultController); const request = jest.fn(); @@ -85,13 +72,13 @@ describe("AnalyticsController", () => { CoreManager.setRESTController({ request: request, ajax: ajax }); }); - it("passes dimensions along to the appropriate endpoint", () => { - Analytics.track("click", { x: "12", y: "40" }); + 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" } }, + 'POST', + 'events/click', + { dimensions: { x: '12', y: '40' } }, ]); }); }); diff --git a/src/__tests__/AnonymousUtils-test.js b/src/__tests__/AnonymousUtils-test.js index 7869bc64f..f64d92bb1 100644 --- a/src/__tests__/AnonymousUtils-test.js +++ b/src/__tests__/AnonymousUtils-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../AnonymousUtils"); +jest.dontMock('../AnonymousUtils'); class MockUser { constructor() { - this.className = "_User"; + this.className = '_User'; this.attributes = {}; } _isLinked() {} @@ -20,7 +20,7 @@ class MockUser { static logInWith() {} } -jest.setMock("../ParseUser", MockUser); +jest.setMock('../ParseUser', MockUser); const mockProvider = { restoreAuthentication() { @@ -28,64 +28,58 @@ const mockProvider = { }, getAuthType() { - return "anonymous"; + return 'anonymous'; }, getAuthData() { return { authData: { - id: "1234", + id: '1234', }, }; }, }; -const AnonymousUtils = require("../AnonymousUtils").default; +const AnonymousUtils = require('../AnonymousUtils').default; -describe("AnonymousUtils", () => { +describe('AnonymousUtils', () => { beforeEach(() => { jest.clearAllMocks(); - jest - .spyOn(AnonymousUtils, "_getAuthProvider") - .mockImplementation(() => mockProvider); + jest.spyOn(AnonymousUtils, '_getAuthProvider').mockImplementation(() => mockProvider); }); - it("can register provider", () => { + it('can register provider', () => { AnonymousUtils._getAuthProvider.mockRestore(); - jest.spyOn(MockUser, "_registerAuthenticationProvider"); + jest.spyOn(MockUser, '_registerAuthenticationProvider'); AnonymousUtils._getAuthProvider(); AnonymousUtils._getAuthProvider(); expect(MockUser._registerAuthenticationProvider).toHaveBeenCalledTimes(1); }); - it("can check user isLinked", () => { + it('can check user isLinked', () => { const user = new MockUser(); - jest.spyOn(user, "_isLinked"); + jest.spyOn(user, '_isLinked'); AnonymousUtils.isLinked(user); expect(user._isLinked).toHaveBeenCalledTimes(1); - expect(user._isLinked).toHaveBeenCalledWith("anonymous"); + expect(user._isLinked).toHaveBeenCalledWith('anonymous'); expect(AnonymousUtils._getAuthProvider).toHaveBeenCalledTimes(1); }); - it("can link user", () => { + it('can link user', () => { const user = new MockUser(); - jest.spyOn(user, "linkWith"); + jest.spyOn(user, 'linkWith'); AnonymousUtils.link(user); expect(user.linkWith).toHaveBeenCalledTimes(1); - expect(user.linkWith).toHaveBeenCalledWith( - "anonymous", - mockProvider.getAuthData(), - undefined - ); + expect(user.linkWith).toHaveBeenCalledWith('anonymous', mockProvider.getAuthData(), undefined); expect(AnonymousUtils._getAuthProvider).toHaveBeenCalledTimes(1); }); - it("can login user", () => { - jest.spyOn(MockUser, "logInWith"); + it('can login user', () => { + jest.spyOn(MockUser, 'logInWith'); AnonymousUtils.logIn(); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); expect(MockUser.logInWith).toHaveBeenCalledWith( - "anonymous", + 'anonymous', mockProvider.getAuthData(), undefined ); diff --git a/src/__tests__/Cloud-test.js b/src/__tests__/Cloud-test.js index 9691b4ae3..370e6393e 100644 --- a/src/__tests__/Cloud-test.js +++ b/src/__tests__/Cloud-test.js @@ -7,20 +7,20 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../Cloud"); -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseQuery"); +jest.dontMock('../Cloud'); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseQuery'); -const Cloud = require("../Cloud"); -const CoreManager = require("../CoreManager"); +const Cloud = require('../Cloud'); +const CoreManager = require('../CoreManager'); const defaultController = CoreManager.getCloudController(); -describe("Cloud", () => { +describe('Cloud', () => { beforeEach(() => { const run = jest.fn(); const getJobsData = jest.fn(); @@ -43,99 +43,79 @@ describe("Cloud", () => { CoreManager.setCloudController({ run, getJobsData, startJob }); }); - it("run throws with an invalid function name", () => { - expect(Cloud.run).toThrow("Cloud function name must be a string."); + it('run throws with an invalid function name', () => { + 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", {}); + 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 }); + 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 }); + Cloud.run('myfunction', {}, { useMasterKey: true }); expect(CoreManager.getCloudController().run.mock.calls[1]).toEqual([ - "myfunction", + 'myfunction', {}, { useMasterKey: true }, ]); - Cloud.run("myfunction", {}, { sessionToken: "asdf1234" }); + Cloud.run('myfunction', {}, { sessionToken: 'asdf1234' }); expect(CoreManager.getCloudController().run.mock.calls[2]).toEqual([ - "myfunction", + 'myfunction', {}, - { sessionToken: "asdf1234" }, + { sessionToken: 'asdf1234' }, ]); - Cloud.run( - "myfunction", - {}, - { useMasterKey: true, sessionToken: "asdf1234" } - ); + Cloud.run('myfunction', {}, { useMasterKey: true, sessionToken: 'asdf1234' }); expect(CoreManager.getCloudController().run.mock.calls[3]).toEqual([ - "myfunction", + 'myfunction', {}, - { useMasterKey: true, sessionToken: "asdf1234" }, + { useMasterKey: true, sessionToken: 'asdf1234' }, ]); }); - it("startJob throws with an invalid job name", () => { - expect(Cloud.startJob).toThrow("Cloud job name must be a string."); + it('startJob throws with an invalid job name', () => { + 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", {}); + it('startJob passes function name and data along', () => { + Cloud.startJob('myJob', {}); expect(CoreManager.getCloudController().startJob.mock.calls[0]).toEqual([ - "myJob", + 'myJob', {}, { useMasterKey: true }, ]); }); - it("startJob passes options", () => { - Cloud.startJob("myJob", {}, { useMasterKey: true }); + it('startJob passes options', () => { + Cloud.startJob('myJob', {}, { useMasterKey: true }); expect(CoreManager.getCloudController().startJob.mock.calls[0]).toEqual([ - "myJob", + 'myJob', {}, { useMasterKey: true }, ]); }); - it("getJobsData passes options", () => { + it('getJobsData passes options', () => { Cloud.getJobsData(); expect(CoreManager.getCloudController().getJobsData.mock.calls[0]).toEqual([ @@ -150,7 +130,7 @@ describe("Cloud", () => { }); }); -describe("CloudController", () => { +describe('CloudController', () => { beforeEach(() => { CoreManager.setCloudController(defaultController); const request = jest.fn(); @@ -164,48 +144,48 @@ describe("CloudController", () => { CoreManager.setRESTController({ request: request, ajax: ajax }); }); - it("run passes encoded requests", () => { - Cloud.run("myfunction", { + it('run passes encoded requests', () => { + Cloud.run('myfunction', { value: 12, when: new Date(Date.UTC(2015, 0, 1)), }); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "POST", - "functions/myfunction", + 'POST', + 'functions/myfunction', { value: 12, - when: { __type: "Date", iso: "2015-01-01T00:00:00.000Z" }, + when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z' }, }, {}, ]); }); - it("run passes options", () => { - Cloud.run("myfunction", { value: 12 }, { useMasterKey: true }); + it('run passes options', () => { + Cloud.run('myfunction', { value: 12 }, { useMasterKey: true }); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "POST", - "functions/myfunction", + 'POST', + 'functions/myfunction', { value: 12, }, { useMasterKey: true }, ]); - Cloud.run("myfunction", { value: 12 }, { sessionToken: "asdf1234" }); + Cloud.run('myfunction', { value: 12 }, { sessionToken: 'asdf1234' }); expect(CoreManager.getRESTController().request.mock.calls[1]).toEqual([ - "POST", - "functions/myfunction", + 'POST', + 'functions/myfunction', { value: 12, }, - { sessionToken: "asdf1234" }, + { sessionToken: 'asdf1234' }, ]); }); - it("run invalid response", (done) => { + it('run invalid response', done => { const request = jest.fn(); request.mockReturnValue( Promise.resolve({ @@ -215,48 +195,48 @@ describe("CloudController", () => { const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); - Cloud.run("myfunction") + 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)); const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); - Cloud.run("myfunction").then(() => { + Cloud.run('myfunction').then(() => { done(); }); }); - it("startJob passes encoded requests", () => { - Cloud.startJob("myJob", { + it('startJob passes encoded requests', () => { + Cloud.startJob('myJob', { value: 12, when: new Date(Date.UTC(2015, 0, 1)), }); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "POST", - "jobs/myJob", + 'POST', + 'jobs/myJob', { value: 12, - when: { __type: "Date", iso: "2015-01-01T00:00:00.000Z" }, + when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z' }, }, { useMasterKey: true }, ]); }); - it("startJob passes options", () => { - Cloud.startJob("myJob", { value: 12 }, { useMasterKey: true }); + it('startJob passes options', () => { + Cloud.startJob('myJob', { value: 12 }, { useMasterKey: true }); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "POST", - "jobs/myJob", + 'POST', + 'jobs/myJob', { value: 12, }, @@ -264,29 +244,29 @@ describe("CloudController", () => { ]); }); - it("getJobsData passes no options", () => { + it('getJobsData passes no options', () => { Cloud.getJobsData(); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "GET", - "cloud_code/jobs/data", + 'GET', + 'cloud_code/jobs/data', null, { useMasterKey: true }, ]); }); - it("getJobsData passes options", () => { + it('getJobsData passes options', () => { Cloud.getJobsData({ useMasterKey: true }); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "GET", - "cloud_code/jobs/data", + 'GET', + 'cloud_code/jobs/data', null, { useMasterKey: true }, ]); }); - it("accepts context on cloud function call", async () => { + it('accepts context on cloud function call', async () => { const request = jest.fn(); request.mockReturnValue(Promise.resolve(undefined)); @@ -295,31 +275,31 @@ describe("CloudController", () => { // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "request"); + jest.spyOn(controller, 'request'); // Save object - const context = { a: "a" }; - await Cloud.run("myfunction", {}, { context: context }); + const context = { a: 'a' }; + await Cloud.run('myfunction', {}, { context: context }); // Validate expect(controller.request.mock.calls[0][3].context).toEqual(context); }); - it("can get job status", async () => { + it('can get job status', async () => { const request = jest.fn(); request.mockReturnValue( Promise.resolve({ - results: [{ className: "_JobStatus", objectId: "jobId1234" }], + results: [{ className: '_JobStatus', objectId: 'jobId1234' }], }) ); CoreManager.setRESTController({ request: request, ajax: jest.fn() }); - await Cloud.getJobStatus("jobId1234"); + await Cloud.getJobStatus('jobId1234'); const [method, path, data, options] = request.mock.calls[0]; - expect(method).toBe("GET"); - expect(path).toBe("classes/_JobStatus"); + expect(method).toBe('GET'); + expect(path).toBe('classes/_JobStatus'); expect(data).toEqual({ limit: 1, where: { - objectId: "jobId1234", + objectId: 'jobId1234', }, }); expect(options.useMasterKey).toBe(true); diff --git a/src/__tests__/CoreManager-test.js b/src/__tests__/CoreManager-test.js index 7d1e77dca..4b4c747ac 100644 --- a/src/__tests__/CoreManager-test.js +++ b/src/__tests__/CoreManager-test.js @@ -7,34 +7,34 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); +jest.dontMock('../CoreManager'); -const CoreManager = require("../CoreManager"); +const CoreManager = require('../CoreManager'); -describe("CoreManager", () => { - it("is initialized with default values", () => { - expect(CoreManager.get("SERVER_URL")).toBe("https://api.parse.com/1"); +describe('CoreManager', () => { + it('is initialized with default values', () => { + expect(CoreManager.get('SERVER_URL')).toBe('https://api.parse.com/1'); }); - it("pulls the version string from package.json", () => { - expect(CoreManager.get("VERSION").length).toBeGreaterThan(0); + it('pulls the version string from package.json', () => { + expect(CoreManager.get('VERSION').length).toBeGreaterThan(0); }); - it("detects when running in node", () => { - expect(CoreManager.get("IS_NODE")).toBe(true); + it('detects when running in node', () => { + expect(CoreManager.get('IS_NODE')).toBe(true); }); - it("can set and retrieve arbitrary values", () => { - expect(CoreManager.get.bind(null, "something")).toThrow( - "Configuration key not found: something" + it('can set and retrieve arbitrary values', () => { + expect(CoreManager.get.bind(null, 'something')).toThrow( + 'Configuration key not found: something' ); - CoreManager.set("something", "a string"); - expect(CoreManager.get("something")).toBe("a string"); + CoreManager.set('something', 'a string'); + expect(CoreManager.get('something')).toBe('a string'); }); - it("requires AnalyticsController to implement certain functionality", () => { + it('requires AnalyticsController to implement certain functionality', () => { expect(CoreManager.setAnalyticsController.bind(null, {})).toThrow( - "AnalyticsController must implement track()" + 'AnalyticsController must implement track()' ); expect( @@ -44,7 +44,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get AnalyticsController", () => { + it('can set and get AnalyticsController', () => { const controller = { track: function () {}, }; @@ -53,9 +53,9 @@ describe("CoreManager", () => { expect(CoreManager.getAnalyticsController()).toBe(controller); }); - it("requires CloudController to implement certain functionality", () => { + it('requires CloudController to implement certain functionality', () => { expect(CoreManager.setCloudController.bind(null, {})).toThrow( - "CloudController must implement run()" + 'CloudController must implement run()' ); expect( @@ -68,7 +68,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get CloudController", () => { + it('can set and get CloudController', () => { const controller = { run: function () {}, getJobsData: function () {}, @@ -80,16 +80,16 @@ describe("CoreManager", () => { expect(CoreManager.getCloudController()).toBe(controller); }); - it("requires ConfigController to implement certain functionality", () => { + it('requires ConfigController to implement certain functionality', () => { expect(CoreManager.setConfigController.bind(null, {})).toThrow( - "ConfigController must implement current()" + 'ConfigController must implement current()' ); expect( CoreManager.setConfigController.bind(null, { current: function () {}, }) - ).toThrow("ConfigController must implement get()"); + ).toThrow('ConfigController must implement get()'); expect( CoreManager.setConfigController.bind(null, { @@ -100,7 +100,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get ConfigController", () => { + it('can set and get ConfigController', () => { const controller = { current: function () {}, get: function () {}, @@ -111,16 +111,16 @@ describe("CoreManager", () => { expect(CoreManager.getConfigController()).toBe(controller); }); - it("requires FileController to implement certain functionality", () => { + it('requires FileController to implement certain functionality', () => { expect(CoreManager.setFileController.bind(null, {})).toThrow( - "FileController must implement saveFile()" + 'FileController must implement saveFile()' ); expect( CoreManager.setFileController.bind(null, { saveFile: function () {}, }) - ).toThrow("FileController must implement saveBase64()"); + ).toThrow('FileController must implement saveBase64()'); expect( CoreManager.setFileController.bind(null, { @@ -130,7 +130,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get FileController", () => { + it('can set and get FileController', () => { const controller = { saveFile: function () {}, saveBase64: function () {}, @@ -140,9 +140,9 @@ describe("CoreManager", () => { expect(CoreManager.getFileController()).toBe(controller); }); - it("requires InstallationController to implement certain functionality", () => { + it('requires InstallationController to implement certain functionality', () => { expect(CoreManager.setInstallationController.bind(null, {})).toThrow( - "InstallationController must implement currentInstallationId()" + 'InstallationController must implement currentInstallationId()' ); expect( @@ -152,7 +152,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get InstallationController", () => { + it('can set and get InstallationController', () => { const controller = { currentInstallationId: function () {}, }; @@ -161,9 +161,9 @@ describe("CoreManager", () => { expect(CoreManager.getInstallationController()).toBe(controller); }); - it("requires PushController to implement certain functionality", () => { + it('requires PushController to implement certain functionality', () => { expect(CoreManager.setPushController.bind(null, {})).toThrow( - "PushController must implement send()" + 'PushController must implement send()' ); expect( @@ -173,7 +173,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get PushController", () => { + it('can set and get PushController', () => { const controller = { send: function () {}, }; @@ -182,23 +182,23 @@ describe("CoreManager", () => { expect(CoreManager.getPushController()).toBe(controller); }); - it("requires ObjectController to implement certain functionality", () => { + it('requires ObjectController to implement certain functionality', () => { expect(CoreManager.setObjectController.bind(null, {})).toThrow( - "ObjectController must implement save()" + 'ObjectController must implement save()' ); expect( CoreManager.setObjectController.bind(null, { save: function () {}, }) - ).toThrow("ObjectController must implement fetch()"); + ).toThrow('ObjectController must implement fetch()'); expect( CoreManager.setObjectController.bind(null, { save: function () {}, fetch: function () {}, }) - ).toThrow("ObjectController must implement destroy()"); + ).toThrow('ObjectController must implement destroy()'); expect( CoreManager.setObjectController.bind(null, { @@ -209,7 +209,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get ObjectController", () => { + it('can set and get ObjectController', () => { const controller = { save: function () {}, fetch: function () {}, @@ -220,7 +220,7 @@ describe("CoreManager", () => { expect(CoreManager.getObjectController()).toBe(controller); }); - it("can set and get ObjectStateController", () => { + it('can set and get ObjectStateController', () => { const controller = { getState: function () {}, initializeState: function () {}, @@ -244,9 +244,9 @@ describe("CoreManager", () => { expect(CoreManager.getObjectStateController()).toBe(controller); }); - it("requires QueryController to implement certain functionality", () => { + it('requires QueryController to implement certain functionality', () => { expect(CoreManager.setQueryController.bind(null, {})).toThrow( - "QueryController must implement find()" + 'QueryController must implement find()' ); expect( @@ -257,7 +257,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get QueryController", () => { + it('can set and get QueryController', () => { const controller = { find: function () {}, aggregate: function () {}, @@ -267,16 +267,16 @@ describe("CoreManager", () => { expect(CoreManager.getQueryController()).toBe(controller); }); - it("requires RESTController to implement certain functionality", () => { + it('requires RESTController to implement certain functionality', () => { expect(CoreManager.setRESTController.bind(null, {})).toThrow( - "RESTController must implement request()" + 'RESTController must implement request()' ); expect( CoreManager.setRESTController.bind(null, { request: function () {}, }) - ).toThrow("RESTController must implement ajax()"); + ).toThrow('RESTController must implement ajax()'); expect( CoreManager.setRESTController.bind(null, { @@ -286,7 +286,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get RESTController", () => { + it('can set and get RESTController', () => { const controller = { request: function () {}, ajax: function () {}, @@ -296,9 +296,9 @@ describe("CoreManager", () => { expect(CoreManager.getRESTController()).toBe(controller); }); - it("requires StorageController to implement certain functionality", () => { + it('requires StorageController to implement certain functionality', () => { expect(CoreManager.setStorageController.bind(null, { async: 0 })).toThrow( - "A synchronous StorageController must implement getItem()" + 'A synchronous StorageController must implement getItem()' ); expect( @@ -306,7 +306,7 @@ describe("CoreManager", () => { async: 0, getItem: function () {}, }) - ).toThrow("A synchronous StorageController must implement setItem()"); + ).toThrow('A synchronous StorageController must implement setItem()'); expect( CoreManager.setStorageController.bind(null, { @@ -314,7 +314,7 @@ describe("CoreManager", () => { getItem: function () {}, setItem: function () {}, }) - ).toThrow("A synchronous StorageController must implement removeItem()"); + ).toThrow('A synchronous StorageController must implement removeItem()'); expect( CoreManager.setStorageController.bind(null, { @@ -327,7 +327,7 @@ describe("CoreManager", () => { ).not.toThrow(); expect(CoreManager.setStorageController.bind(null, { async: 1 })).toThrow( - "An async StorageController must implement getItemAsync()" + 'An async StorageController must implement getItemAsync()' ); expect( @@ -335,7 +335,7 @@ describe("CoreManager", () => { async: 1, getItemAsync: function () {}, }) - ).toThrow("An async StorageController must implement setItemAsync()"); + ).toThrow('An async StorageController must implement setItemAsync()'); expect( CoreManager.setStorageController.bind(null, { @@ -343,7 +343,7 @@ describe("CoreManager", () => { getItemAsync: function () {}, setItemAsync: function () {}, }) - ).toThrow("An async StorageController must implement removeItemAsync()"); + ).toThrow('An async StorageController must implement removeItemAsync()'); expect( CoreManager.setStorageController.bind(null, { @@ -356,7 +356,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get StorageController", () => { + it('can set and get StorageController', () => { const controller = { async: 0, getItem: function () {}, @@ -369,9 +369,9 @@ describe("CoreManager", () => { expect(CoreManager.getStorageController()).toBe(controller); }); - it("requires SchemaController to implement certain functionality", () => { + it('requires SchemaController to implement certain functionality', () => { expect(CoreManager.setSchemaController.bind(null, {})).toThrow( - "SchemaController must implement get()" + 'SchemaController must implement get()' ); expect( @@ -386,7 +386,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get SchemaController", () => { + it('can set and get SchemaController', () => { const controller = { send: function () {}, get: function () {}, @@ -400,9 +400,9 @@ describe("CoreManager", () => { expect(CoreManager.getSchemaController()).toBe(controller); }); - it("requires LocalDatastoreController to implement certain functionality", () => { + it('requires LocalDatastoreController to implement certain functionality', () => { expect(CoreManager.setLocalDatastoreController.bind(null, {})).toThrow( - "LocalDatastoreController must implement pinWithName()" + 'LocalDatastoreController must implement pinWithName()' ); expect( @@ -416,7 +416,7 @@ describe("CoreManager", () => { ).not.toThrow(); }); - it("can set and get setLocalDatastoreController", () => { + it('can set and get setLocalDatastoreController', () => { const controller = { fromPinWithName: function () {}, pinWithName: function () {}, @@ -429,7 +429,7 @@ describe("CoreManager", () => { expect(CoreManager.getLocalDatastoreController()).toBe(controller); }); - it("can set and get WebSocketController", () => { + it('can set and get WebSocketController', () => { const controller = { onopen: function () {}, onmessage: function () {}, diff --git a/src/__tests__/FacebookUtils-test.js b/src/__tests__/FacebookUtils-test.js index b0b8d4043..b846bfec7 100644 --- a/src/__tests__/FacebookUtils-test.js +++ b/src/__tests__/FacebookUtils-test.js @@ -7,11 +7,11 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../FacebookUtils"); +jest.dontMock('../FacebookUtils'); class MockUser { constructor() { - this.className = "_User"; + this.className = '_User'; this.attributes = {}; } _isLinked() {} @@ -21,76 +21,68 @@ class MockUser { static logInWith() {} } -jest.setMock("../ParseUser", MockUser); +jest.setMock('../ParseUser', MockUser); -const FacebookUtils = require("../FacebookUtils").default; +const FacebookUtils = require('../FacebookUtils').default; -describe("FacebookUtils", () => { +describe('FacebookUtils', () => { beforeEach(() => { jest.clearAllMocks(); const authResponse = { - userID: "test", - accessToken: "test", - expiresIn: "test", // Should be unix timestamp + userID: 'test', + accessToken: 'test', + expiresIn: 'test', // Should be unix timestamp }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, getAuthResponse: () => authResponse, }; }); - it("can not init without FB SDK", () => { + it('can not init without FB SDK', () => { global.FB = undefined; try { FacebookUtils.init(); } catch (e) { - expect(e.message).toBe( - "The Facebook JavaScript SDK must be loaded before calling init." - ); + expect(e.message).toBe('The Facebook JavaScript SDK must be loaded before calling init.'); } }); - it("can not login without init", async () => { + it('can not login without init', async () => { try { await FacebookUtils.logIn(); } catch (e) { - expect(e.message).toBe( - "You must initialize FacebookUtils before calling logIn." - ); + expect(e.message).toBe('You must initialize FacebookUtils before calling logIn.'); } }); - it("can not link without init", async () => { + it('can not link without init', async () => { try { const user = new MockUser(); await FacebookUtils.link(user); } catch (e) { - expect(e.message).toBe( - "You must initialize FacebookUtils before calling link." - ); + expect(e.message).toBe('You must initialize FacebookUtils before calling link.'); } }); - it("can not unlink without init", () => { + it('can not unlink without init', () => { try { const user = new MockUser(); FacebookUtils.unlink(user); } catch (e) { - expect(e.message).toBe( - "You must initialize FacebookUtils before calling unlink." - ); + expect(e.message).toBe('You must initialize FacebookUtils before calling unlink.'); } }); - it("can init", () => { + it('can init', () => { FacebookUtils.init(); }); - it("can init with options", () => { - jest.spyOn(console, "warn").mockImplementationOnce(() => { + it('can init with options', () => { + jest.spyOn(console, 'warn').mockImplementationOnce(() => { return { call: () => {}, }; @@ -99,224 +91,217 @@ describe("FacebookUtils", () => { expect(console.warn).toHaveBeenCalled(); }); - it("can link", async () => { + it('can link', async () => { FacebookUtils.init(); const user = new MockUser(); await FacebookUtils.link(user); }); - it("can link with permission string", async () => { + it('can link with permission string', async () => { FacebookUtils.init(); const user = new MockUser(); - await FacebookUtils.link(user, "public_profile"); + await FacebookUtils.link(user, 'public_profile'); }); - it("can link with authData object", async () => { + it('can link with authData object', async () => { FacebookUtils.init(); const user = new MockUser(); const authData = { - id: "1234", + id: '1234', }; - jest.spyOn(user, "linkWith"); + jest.spyOn(user, 'linkWith'); await FacebookUtils.link(user, authData); - expect(user.linkWith).toHaveBeenCalledWith( - "facebook", - { authData: { id: "1234" } }, - undefined - ); + expect(user.linkWith).toHaveBeenCalledWith('facebook', { authData: { id: '1234' } }, undefined); }); - it("can link with options", async () => { + it('can link with options', async () => { FacebookUtils.init(); const user = new MockUser(); - jest.spyOn(user, "linkWith"); + jest.spyOn(user, 'linkWith'); await FacebookUtils.link(user, {}, { useMasterKey: true }); expect(user.linkWith).toHaveBeenCalledWith( - "facebook", + 'facebook', { authData: {} }, { useMasterKey: true } ); }); - it("can check isLinked", async () => { + it('can check isLinked', async () => { FacebookUtils.init(); const user = new MockUser(); - jest.spyOn(user, "_isLinked"); + jest.spyOn(user, '_isLinked'); await FacebookUtils.isLinked(user); - expect(user._isLinked).toHaveBeenCalledWith("facebook"); + expect(user._isLinked).toHaveBeenCalledWith('facebook'); }); - it("can unlink", async () => { + it('can unlink', async () => { FacebookUtils.init(); const user = new MockUser(); - const spy = jest.spyOn(user, "_unlinkFrom"); + const spy = jest.spyOn(user, '_unlinkFrom'); await FacebookUtils.unlink(user); expect(user._unlinkFrom).toHaveBeenCalledTimes(1); spy.mockRestore(); }); - it("can login", async () => { + it('can login', async () => { FacebookUtils.init(); await FacebookUtils.logIn(); }); - it("can login with permission string", async () => { + it('can login with permission string', async () => { FacebookUtils.init(); - jest.spyOn(MockUser, "logInWith"); - await FacebookUtils.logIn("public_profile"); + jest.spyOn(MockUser, 'logInWith'); + await FacebookUtils.logIn('public_profile'); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); }); - it("can login with authData", async () => { + it('can login with authData', async () => { FacebookUtils.init(); - jest.spyOn(MockUser, "logInWith"); - await FacebookUtils.logIn({ id: "1234" }); + jest.spyOn(MockUser, 'logInWith'); + await FacebookUtils.logIn({ id: '1234' }); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); }); - it("can login with options", async () => { + it('can login with options', async () => { FacebookUtils.init(); - jest.spyOn(MockUser, "logInWith"); + jest.spyOn(MockUser, 'logInWith'); await FacebookUtils.logIn({}, { useMasterKey: true }); expect(MockUser.logInWith).toHaveBeenCalledWith( - "facebook", + 'facebook', { authData: {} }, { useMasterKey: true } ); }); - it("provider getAuthType", async () => { + it('provider getAuthType', async () => { const provider = FacebookUtils._getAuthProvider(); - expect(provider.getAuthType()).toBe("facebook"); + expect(provider.getAuthType()).toBe('facebook'); }); - it("provider deauthenticate", async () => { + it('provider deauthenticate', async () => { const provider = FacebookUtils._getAuthProvider(); - jest.spyOn(provider, "restoreAuthentication"); + jest.spyOn(provider, 'restoreAuthentication'); provider.deauthenticate(); expect(provider.restoreAuthentication).toHaveBeenCalled(); }); }); -describe("FacebookUtils provider", () => { +describe('FacebookUtils provider', () => { beforeEach(() => { jest.clearAllMocks(); }); - it("restoreAuthentication", async () => { + it('restoreAuthentication', async () => { const provider = FacebookUtils._getAuthProvider(); const didRestore = provider.restoreAuthentication(); expect(didRestore).toBe(true); }); - it("restoreAuthentication with invalid authData", async () => { + it('restoreAuthentication with invalid authData', async () => { global.FB = { init: () => {}, logout: () => {}, getAuthResponse: () => { - return { userID: "5678" }; + return { userID: '5678' }; }, }; - jest.spyOn(global.FB, "logout"); + jest.spyOn(global.FB, 'logout'); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: "1234" }); + provider.restoreAuthentication({ id: '1234' }); expect(global.FB.logout).toHaveBeenCalled(); }); - it("restoreAuthentication with valid authData", async () => { + it('restoreAuthentication with valid authData', async () => { global.FB = { init: () => {}, getAuthResponse: () => { - return { userID: "1234" }; + return { userID: '1234' }; }, }; FacebookUtils.init({ status: false }); - jest.spyOn(global.FB, "init"); + jest.spyOn(global.FB, 'init'); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: "1234" }); + provider.restoreAuthentication({ id: '1234' }); expect(global.FB.init).toHaveBeenCalled(); }); - it("restoreAuthentication with valid authData", async () => { + it('restoreAuthentication with valid authData', async () => { global.FB = { init: () => {}, getAuthResponse: () => { - return { userID: "1234" }; + return { userID: '1234' }; }, }; FacebookUtils.init({ status: false }); - jest.spyOn(global.FB, "init"); + 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 () => { + it('authenticate without FB error', async () => { global.FB = undefined; const options = { error: () => {}, }; - jest.spyOn(options, "error"); + jest.spyOn(options, 'error'); const provider = FacebookUtils._getAuthProvider(); try { provider.authenticate(options); } catch (e) { - expect(options.error).toHaveBeenCalledWith( - provider, - "Facebook SDK not found." - ); + expect(options.error).toHaveBeenCalledWith(provider, 'Facebook SDK not found.'); } }); - it("authenticate with FB response", async () => { + it('authenticate with FB response', async () => { const authResponse = { - userID: "1234", - accessToken: "access_token", - expiresIn: "2000-01-01", + userID: '1234', + accessToken: 'access_token', + expiresIn: '2000-01-01', }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, }; const options = { success: () => {}, }; - jest.spyOn(options, "success"); + jest.spyOn(options, 'success'); const provider = FacebookUtils._getAuthProvider(); provider.authenticate(options); expect(options.success).toHaveBeenCalledWith(provider, { - access_token: "access_token", + access_token: 'access_token', expiration_date: null, - id: "1234", + id: '1234', }); }); - it("authenticate with no FB response", async () => { + it('authenticate with no FB response', async () => { global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({}); }, }; const options = { error: () => {}, }; - jest.spyOn(options, "error"); + jest.spyOn(options, 'error'); const provider = FacebookUtils._getAuthProvider(); provider.authenticate(options); expect(options.error).toHaveBeenCalledWith(provider, {}); }); - it("getAuthType", async () => { + it('getAuthType', async () => { const provider = FacebookUtils._getAuthProvider(); - expect(provider.getAuthType()).toBe("facebook"); + expect(provider.getAuthType()).toBe('facebook'); }); - it("deauthenticate", async () => { + it('deauthenticate', async () => { const provider = FacebookUtils._getAuthProvider(); - jest.spyOn(provider, "restoreAuthentication"); + jest.spyOn(provider, 'restoreAuthentication'); provider.deauthenticate(); expect(provider.restoreAuthentication).toHaveBeenCalled(); }); diff --git a/src/__tests__/Hooks-test.js b/src/__tests__/Hooks-test.js index 25b9a4aec..dcf3af16e 100644 --- a/src/__tests__/Hooks-test.js +++ b/src/__tests__/Hooks-test.js @@ -7,19 +7,19 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../ParseHooks"); -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ParseError"); +jest.dontMock('../ParseHooks'); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ParseError'); -const Hooks = require("../ParseHooks"); -const CoreManager = require("../CoreManager"); +const Hooks = require('../ParseHooks'); +const CoreManager = require('../CoreManager'); const defaultController = CoreManager.getHooksController(); const { sendRequest } = defaultController; -describe("Hooks", () => { +describe('Hooks', () => { beforeEach(() => { const run = jest.fn(); run.mockReturnValue( @@ -31,250 +31,247 @@ describe("Hooks", () => { CoreManager.setHooksController(defaultController); }); - it("shoud properly build GET functions", () => { + it('shoud properly build GET functions', () => { Hooks.getFunctions(); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "GET", - "/hooks/functions", + 'GET', + '/hooks/functions', ]); }); - it("shoud properly build GET triggers", () => { + it('shoud properly build GET triggers', () => { Hooks.getTriggers(); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "GET", - "/hooks/triggers", + 'GET', + '/hooks/triggers', ]); }); - it("shoud properly build GET function", () => { - Hooks.getFunction("functionName"); + it('shoud properly build GET function', () => { + Hooks.getFunction('functionName'); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "GET", - "/hooks/functions/functionName", + 'GET', + '/hooks/functions/functionName', ]); }); - it("shoud properly build GET trigger", () => { - Hooks.getTrigger("MyClass", "beforeSave"); + it('shoud properly build GET trigger', () => { + Hooks.getTrigger('MyClass', 'beforeSave'); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "GET", - "/hooks/triggers/MyClass/beforeSave", + 'GET', + '/hooks/triggers/MyClass/beforeSave', ]); }); - it("shoud properly build POST function", () => { - Hooks.createFunction("myFunction", "https://dummy.com"); + it('shoud properly build POST function', () => { + Hooks.createFunction('myFunction', 'https://dummy.com'); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "POST", - "/hooks/functions", + 'POST', + '/hooks/functions', { - functionName: "myFunction", - url: "https://dummy.com", + functionName: 'myFunction', + url: 'https://dummy.com', }, ]); }); - it("shoud properly build POST trigger", () => { - Hooks.createTrigger("MyClass", "beforeSave", "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", + 'POST', + '/hooks/triggers', { - className: "MyClass", - triggerName: "beforeSave", - url: "https://dummy.com", + className: 'MyClass', + triggerName: 'beforeSave', + url: 'https://dummy.com', }, ]); }); - it("shoud properly build PUT function", () => { - Hooks.updateFunction("myFunction", "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", + 'PUT', + '/hooks/functions/myFunction', { - url: "https://dummy.com", + url: 'https://dummy.com', }, ]); }); - it("shoud properly build PUT trigger", () => { - Hooks.updateTrigger("MyClass", "beforeSave", "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", + 'PUT', + '/hooks/triggers/MyClass/beforeSave', { - url: "https://dummy.com", + url: 'https://dummy.com', }, ]); }); - it("shoud properly build removeFunction", () => { - Hooks.removeFunction("myFunction"); + it('shoud properly build removeFunction', () => { + Hooks.removeFunction('myFunction'); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "PUT", - "/hooks/functions/myFunction", - { __op: "Delete" }, + 'PUT', + '/hooks/functions/myFunction', + { __op: 'Delete' }, ]); }); - it("shoud properly build removeTrigger", () => { - Hooks.removeTrigger("MyClass", "beforeSave"); + it('shoud properly build removeTrigger', () => { + Hooks.removeTrigger('MyClass', 'beforeSave'); expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ - "PUT", - "/hooks/triggers/MyClass/beforeSave", - { __op: "Delete" }, + 'PUT', + '/hooks/triggers/MyClass/beforeSave', + { __op: 'Delete' }, ]); }); - it("shoud throw invalid create", async (done) => { - const p1 = Hooks.create({ functionName: "myFunction" }) + it('shoud throw invalid create', async done => { + const p1 = Hooks.create({ functionName: 'myFunction' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p2 = Hooks.create({ url: "http://dummy.com" }) + const p2 = Hooks.create({ url: 'http://dummy.com' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p3 = Hooks.create({ className: "MyClass" }) + const p3 = Hooks.create({ className: 'MyClass' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p4 = Hooks.create({ className: "MyClass", url: "http://dummy.com" }) + const p4 = Hooks.create({ className: 'MyClass', url: 'http://dummy.com' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p5 = Hooks.create({ className: "MyClass", triggerName: "beforeSave" }) + const p5 = Hooks.create({ className: 'MyClass', triggerName: 'beforeSave' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + 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" }) + it('shoud throw invalid update', async done => { + const p1 = Hooks.update({ functionssName: 'myFunction' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p2 = Hooks.update({ className: "MyClass" }) + const p2 = Hooks.update({ className: 'MyClass' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p3 = Hooks.update({ className: "MyClass", url: "http://dummy.com" }) + const p3 = Hooks.update({ className: 'MyClass', url: 'http://dummy.com' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + 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" }) + it('shoud throw invalid remove', async done => { + const p1 = Hooks.remove({ functionssName: 'myFunction' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p2 = Hooks.remove({ className: "MyClass" }) + const p2 = Hooks.remove({ className: 'MyClass' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); - const p3 = Hooks.remove({ className: "MyClass", url: "http://dummy.com" }) + const p3 = Hooks.remove({ className: 'MyClass', url: 'http://dummy.com' }) .then(() => { - done.fail("should not succeed"); + done.fail('should not succeed'); }) - .catch((err) => { + .catch(err => { expect(err.code).toBe(143); - expect(err.error).toBe("invalid hook declaration"); + expect(err.error).toBe('invalid hook declaration'); }); await Promise.all([p1, p2, p3]); done(); }); - it("should sendRequest", async () => { + it('should sendRequest', async () => { defaultController.sendRequest = sendRequest; const request = function () { return Promise.resolve(12); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); - const decoded = await defaultController.sendRequest( - "POST", - "hooks/triggers/myhook" - ); + const decoded = await defaultController.sendRequest('POST', 'hooks/triggers/myhook'); expect(decoded).toBe(12); }); - it("handle sendRequest error", async () => { + it('handle sendRequest error', async () => { defaultController.sendRequest = sendRequest; const request = function () { return Promise.resolve(undefined); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); try { - await defaultController.sendRequest("POST", "hooks/triggers/myhook"); + await defaultController.sendRequest('POST', 'hooks/triggers/myhook'); expect(false).toBe(true); } catch (e) { - expect(e.message).toBe("The server returned an invalid response."); + expect(e.message).toBe('The server returned an invalid response.'); } }); }); diff --git a/src/__tests__/InstallationController-test.js b/src/__tests__/InstallationController-test.js index ed4ec76c4..7d22f2466 100644 --- a/src/__tests__/InstallationController-test.js +++ b/src/__tests__/InstallationController-test.js @@ -7,67 +7,67 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../InstallationController"); -jest.dontMock("../Storage"); -jest.dontMock("../StorageController.default"); -jest.mock("uuid/v4", () => { +jest.dontMock('../CoreManager'); +jest.dontMock('../InstallationController'); +jest.dontMock('../Storage'); +jest.dontMock('../StorageController.default'); +jest.mock('uuid/v4', () => { let value = 0; - return () => value++ + ""; + return () => value++ + ''; }); -const CoreManager = require("../CoreManager"); -const InstallationController = require("../InstallationController"); -const Storage = require("../Storage"); +const CoreManager = require('../CoreManager'); +const InstallationController = require('../InstallationController'); +const Storage = require('../Storage'); -describe("InstallationController", () => { +describe('InstallationController', () => { beforeEach(() => { - CoreManager.set("APPLICATION_ID", "A"); - CoreManager.set("JAVASCRIPT_KEY", "B"); + CoreManager.set('APPLICATION_ID', 'A'); + CoreManager.set('JAVASCRIPT_KEY', 'B'); Storage._clear(); InstallationController._clearCache(); }); - it("generates a new installation id when there is none", (done) => { - InstallationController.currentInstallationId().then((iid) => { - expect(typeof iid).toBe("string"); + 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) => { + .then(i => { iid = i; Storage._clear(); return InstallationController.currentInstallationId(); }) - .then((i) => { + .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) => { + .then(i => { iid = i; InstallationController._clearCache(); return InstallationController.currentInstallationId(); }) - .then((i) => { + .then(i => { expect(i).toBe(iid); done(); }); }); - it("can set installation id", (done) => { - const iid = "12345678"; + 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 e690dc137..812ebb978 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -7,33 +7,33 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../LiveQueryClient"); -jest.dontMock("../arrayContainsObject"); -jest.dontMock("../canBeSerialized"); -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../equals"); -jest.dontMock("../escape"); -jest.dontMock("../promiseUtils"); -jest.dontMock("../EventEmitter"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../parseDate"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../RESTController"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../TaskQueue"); -jest.dontMock("../unique"); -jest.dontMock("../UniqueInstanceStateController"); -jest.dontMock("../unsavedChildren"); -jest.dontMock("../ParseACL"); -jest.dontMock("../ParseQuery"); -jest.dontMock("../LiveQuerySubscription"); -jest.dontMock("../LocalDatastore"); +jest.dontMock('../LiveQueryClient'); +jest.dontMock('../arrayContainsObject'); +jest.dontMock('../canBeSerialized'); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../equals'); +jest.dontMock('../escape'); +jest.dontMock('../promiseUtils'); +jest.dontMock('../EventEmitter'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../parseDate'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../RESTController'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../TaskQueue'); +jest.dontMock('../unique'); +jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock('../unsavedChildren'); +jest.dontMock('../ParseACL'); +jest.dontMock('../ParseQuery'); +jest.dontMock('../LiveQuerySubscription'); +jest.dontMock('../LocalDatastore'); jest.useFakeTimers(); @@ -41,55 +41,53 @@ const mockLocalDatastore = { isEnabled: false, _updateObjectIfPinned: jest.fn(), }; -jest.setMock("../LocalDatastore", mockLocalDatastore); +jest.setMock('../LocalDatastore', mockLocalDatastore); -const CoreManager = require("../CoreManager"); -const LiveQueryClient = require("../LiveQueryClient").default; -const ParseObject = require("../ParseObject").default; -const ParseQuery = require("../ParseQuery").default; -const { resolvingPromise } = require("../promiseUtils"); -const events = require("events"); +const CoreManager = require('../CoreManager'); +const LiveQueryClient = require('../LiveQueryClient').default; +const ParseObject = require('../ParseObject').default; +const ParseQuery = require('../ParseQuery').default; +const { resolvingPromise } = require('../promiseUtils'); +const events = require('events'); CoreManager.setLocalDatastore(mockLocalDatastore); -describe("LiveQueryClient", () => { +describe('LiveQueryClient', () => { beforeEach(() => { mockLocalDatastore.isEnabled = false; }); - it("serverURL required", () => { + it('serverURL required', () => { expect(() => { new LiveQueryClient({}); - }).toThrow( - "You need to set a proper Parse LiveQuery server url before using 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({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); - liveQueryClient.on("error", (error) => { - expect(error).toBe("Can not find WebSocket implementation"); + liveQueryClient.on('error', error => { + expect(error).toBe('Can not find WebSocket implementation'); CoreManager.setWebSocketController(WebSocketImplementation); done(); }); liveQueryClient.open(); }); - it("can unsubscribe", async () => { + it('can unsubscribe', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), @@ -106,18 +104,18 @@ describe("LiveQueryClient", () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "unsubscribe", + op: 'unsubscribe', requestId: 1, }); }); - it("can handle open / close states", () => { + it('can handle open / close states', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); expect(liveQueryClient.shouldOpen()).toBe(true); liveQueryClient.close(); @@ -126,23 +124,23 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.shouldOpen()).toBe(false); }); - it("set undefined sessionToken default", () => { + it('set undefined sessionToken default', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', }); expect(liveQueryClient.sessionToken).toBe(undefined); }); - it("can connect to server", () => { + it('can connect to server', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Mock _getWebSocketImplementation liveQueryClient._getWebSocketImplementation = function () { @@ -157,7 +155,7 @@ describe("LiveQueryClient", () => { liveQueryClient.open(); // Verify inner state - expect(liveQueryClient.state).toEqual("connecting"); + expect(liveQueryClient.state).toEqual('connecting'); // Verify handlers liveQueryClient.socket.onopen({}); expect(liveQueryClient._handleWebSocketOpen).toBeCalled(); @@ -169,13 +167,13 @@ describe("LiveQueryClient", () => { expect(liveQueryClient._handleWebSocketError).toBeCalled(); }); - it("can handle WebSocket open message", () => { + it('can handle WebSocket open message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), @@ -186,23 +184,23 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.socket.send).toBeCalled(); const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); - expect(message.op).toEqual("connect"); - expect(message.applicationId).toEqual("applicationId"); - expect(message.javascriptKey).toEqual("javascriptKey"); - expect(message.masterKey).toEqual("masterKey"); - expect(message.sessionToken).toEqual("sessionToken"); + expect(message.op).toEqual('connect'); + expect(message.applicationId).toEqual('applicationId'); + expect(message.javascriptKey).toEqual('javascriptKey'); + expect(message.masterKey).toEqual('masterKey'); + expect(message.sessionToken).toEqual('sessionToken'); }); - it("can handle WebSocket connected response message", async () => { + it('can handle WebSocket connected response message', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const data = { - op: "connected", + op: 'connected', clientId: 1, }; const event = { @@ -210,7 +208,7 @@ describe("LiveQueryClient", () => { }; // Register checked in advance let isChecked = false; - liveQueryClient.on("open", function () { + liveQueryClient.on('open', function () { isChecked = true; }); @@ -219,19 +217,19 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); expect(liveQueryClient.id).toBe(1); await liveQueryClient.connectPromise; - expect(liveQueryClient.state).toEqual("connected"); + expect(liveQueryClient.state).toEqual('connected'); }); - it("can handle WebSocket reconnect on connected response message", async () => { + it('can handle WebSocket reconnect on connected response message', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const data = { - op: "connected", + op: 'connected', clientId: 1, }; const event = { @@ -239,27 +237,27 @@ describe("LiveQueryClient", () => { }; // Register checked in advance let isChecked = false; - liveQueryClient.on("open", function () { + liveQueryClient.on('open', function () { isChecked = true; }); - jest.spyOn(liveQueryClient, "resubscribe"); + jest.spyOn(liveQueryClient, 'resubscribe'); liveQueryClient._handleReconnect(); liveQueryClient._handleWebSocketMessage(event); expect(isChecked).toBe(true); expect(liveQueryClient.id).toBe(1); await liveQueryClient.connectPromise; - expect(liveQueryClient.state).toEqual("connected"); + expect(liveQueryClient.state).toEqual('connected'); expect(liveQueryClient.resubscribe).toHaveBeenCalledTimes(1); }); - it("can handle WebSocket subscribed response message", () => { + it('can handle WebSocket subscribed response message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -267,7 +265,7 @@ describe("LiveQueryClient", () => { liveQueryClient.subscriptions.set(1, subscription); const data = { - op: "subscribed", + op: 'subscribed', clientId: 1, requestId: 1, }; @@ -276,7 +274,7 @@ describe("LiveQueryClient", () => { }; // Register checked in advance let isChecked = false; - subscription.on("open", function () { + subscription.on('open', function () { isChecked = true; }); @@ -285,20 +283,20 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket unsubscribed response message", () => { + it('can handle WebSocket unsubscribed response message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); liveQueryClient.subscriptions.set(1, subscription); const data = { - op: "unsubscribed", + op: 'unsubscribed', clientId: 1, requestId: 1, }; @@ -309,27 +307,27 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.subscriptions.size).toBe(1); }); - it("can handle WebSocket error response message", () => { + it('can handle WebSocket error response message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const data = { - op: "error", + op: 'error', clientId: 1, - error: "error", + error: 'error', }; const event = { 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"); + expect(error).toEqual('error'); }); liveQueryClient._handleWebSocketMessage(event); @@ -337,32 +335,32 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket error while subscribing", () => { + it('can handle WebSocket error while subscribing', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); liveQueryClient.subscriptions.set(1, subscription); const data = { - op: "error", + op: 'error', clientId: 1, requestId: 1, - error: "error thrown", + error: 'error thrown', }; const event = { 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"); + expect(error).toEqual('error thrown'); }); liveQueryClient._handleWebSocketMessage(event); @@ -371,21 +369,21 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket event response message", () => { + it('can handle WebSocket event response message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject("Test"); - object.set("key", "value"); + const object = new ParseObject('Test'); + object.set('key', 'value'); const data = { - op: "create", + op: 'create', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -395,11 +393,11 @@ describe("LiveQueryClient", () => { }; // 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(); - expect(parseObject.get("__type")).toBeUndefined(); + expect(parseObject.get('key')).toEqual('value'); + expect(parseObject.get('className')).toBeUndefined(); + expect(parseObject.get('__type')).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -407,18 +405,18 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket event response message without subscription", () => { + it('can handle WebSocket event response message without subscription', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); - const object = new ParseObject("Test"); - object.set("key", "value"); + const object = new ParseObject('Test'); + object.set('key', 'value'); const data = { - op: "create", + op: 'create', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -429,23 +427,23 @@ describe("LiveQueryClient", () => { liveQueryClient._handleWebSocketMessage(event); }); - it("can handle WebSocket response with original", () => { + it('can handle WebSocket response with original', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject("Test"); - const original = new ParseObject("Test"); - object.set("key", "value"); - original.set("key", "old"); + const object = new ParseObject('Test'); + const original = new ParseObject('Test'); + object.set('key', 'value'); + original.set('key', 'old'); const data = { - op: "update", + op: 'update', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -456,15 +454,15 @@ describe("LiveQueryClient", () => { }; // Register checked in advance let isChecked = false; - subscription.on("update", (parseObject, parseOriginalObject) => { + subscription.on('update', (parseObject, parseOriginalObject) => { isChecked = true; - expect(parseObject.get("key")).toEqual("value"); - expect(parseObject.get("className")).toBeUndefined(); - expect(parseObject.get("__type")).toBeUndefined(); + expect(parseObject.get('key')).toEqual('value'); + expect(parseObject.get('className')).toBeUndefined(); + expect(parseObject.get('__type')).toBeUndefined(); - expect(parseOriginalObject.get("key")).toEqual("old"); - expect(parseOriginalObject.get("className")).toBeUndefined(); - expect(parseOriginalObject.get("__type")).toBeUndefined(); + expect(parseOriginalObject.get('key')).toEqual('old'); + expect(parseOriginalObject.get('className')).toBeUndefined(); + expect(parseOriginalObject.get('__type')).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -472,23 +470,23 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket response override data on update", () => { + it('can handle WebSocket response override data on update', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject("Test"); - const original = new ParseObject("Test"); - object.set("key", "value"); - original.set("key", "old"); + const object = new ParseObject('Test'); + const original = new ParseObject('Test'); + object.set('key', 'value'); + original.set('key', 'old'); const data = { - op: "update", + op: 'update', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -499,18 +497,18 @@ describe("LiveQueryClient", () => { }; jest - .spyOn(mockLocalDatastore, "_updateObjectIfPinned") + .spyOn(mockLocalDatastore, '_updateObjectIfPinned') .mockImplementationOnce(() => Promise.resolve()); const spy = jest - .spyOn(ParseObject, "fromJSON") + .spyOn(ParseObject, 'fromJSON') .mockImplementationOnce(() => original) .mockImplementationOnce(() => object); mockLocalDatastore.isEnabled = true; let isChecked = false; - subscription.on("update", () => { + subscription.on('update', () => { isChecked = true; }); @@ -524,25 +522,25 @@ describe("LiveQueryClient", () => { spy.mockRestore(); }); - it("can handle WebSocket response unset field", async () => { + it('can handle WebSocket response unset field', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const object = new ParseObject("Test"); - const original = new ParseObject("Test"); - const pointer = new ParseObject("PointerTest"); - pointer.id = "1234"; - original.set("pointer", pointer); + const object = new ParseObject('Test'); + const original = new ParseObject('Test'); + const pointer = new ParseObject('PointerTest'); + pointer.id = '1234'; + original.set('pointer', pointer); const data = { - op: "update", + op: 'update', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -552,7 +550,7 @@ describe("LiveQueryClient", () => { data: JSON.stringify(data), }; let isChecked = false; - subscription.on("update", (parseObject, parseOriginalObject) => { + subscription.on('update', (parseObject, parseOriginalObject) => { isChecked = true; expect(parseObject.toJSON().pointer).toBeUndefined(); expect(parseOriginalObject.toJSON().pointer.objectId).toEqual(pointer.id); @@ -563,24 +561,24 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("can handle WebSocket close message", () => { + it('can handle WebSocket close message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + 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; }); @@ -590,24 +588,24 @@ describe("LiveQueryClient", () => { expect(isCheckedAgain).toBe(true); }); - it("can handle WebSocket close message while disconnected", () => { + it('can handle WebSocket close message while disconnected', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + 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(); @@ -618,20 +616,20 @@ describe("LiveQueryClient", () => { expect(isCheckedAgain).toBe(true); }); - it("can handle reconnect", () => { + it('can handle reconnect', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.open = jest.fn(); const attempts = liveQueryClient.attempts; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual("reconnecting"); + expect(liveQueryClient.state).toEqual('reconnecting'); jest.runOnlyPendingTimers(); @@ -639,25 +637,25 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.open).toBeCalled(); }); - it("can handle reconnect and clear handler", () => { + it('can handle reconnect and clear handler', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.open = jest.fn(); const attempts = liveQueryClient.attempts; - liveQueryClient.state = "disconnected"; + liveQueryClient.state = 'disconnected'; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual("disconnected"); + expect(liveQueryClient.state).toEqual('disconnected'); - liveQueryClient.state = "connected"; + liveQueryClient.state = 'connected'; liveQueryClient._handleReconnect(); - expect(liveQueryClient.state).toEqual("reconnecting"); + expect(liveQueryClient.state).toEqual('reconnecting'); liveQueryClient._handleReconnect(); jest.runOnlyPendingTimers(); @@ -666,17 +664,17 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.open).toBeCalled(); }); - it("can handle WebSocket error message", () => { + it('can handle WebSocket error message', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const error = {}; let isChecked = false; - liveQueryClient.on("error", function (errorAgain) { + liveQueryClient.on('error', function (errorAgain) { isChecked = true; expect(errorAgain).toEqual(error); }); @@ -686,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", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); const error = {}; - subscription.on("error", (errorAgain) => { + subscription.on('error', errorAgain => { expect(errorAgain).toEqual(error); done(); }); @@ -705,30 +703,30 @@ describe("LiveQueryClient", () => { liveQueryClient._handleWebSocketError(error); }); - it("can handle WebSocket reconnect on error event", () => { + it('can handle WebSocket reconnect on error event', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); expect(liveQueryClient.additionalProperties).toBe(true); const data = { - op: "error", + op: 'error', code: 1, reconnect: true, - error: "Additional properties not allowed", + error: 'Additional properties not allowed', }; const event = { data: JSON.stringify(data), }; let isChecked = false; - liveQueryClient.on("error", function (error) { + liveQueryClient.on('error', function (error) { isChecked = true; expect(error).toEqual(data.error); }); - const spy = jest.spyOn(liveQueryClient, "_handleReconnect"); + const spy = jest.spyOn(liveQueryClient, '_handleReconnect'); liveQueryClient._handleWebSocketMessage(event); expect(isChecked).toBe(true); @@ -737,19 +735,19 @@ describe("LiveQueryClient", () => { spy.mockRestore(); }); - it("can subscribe", async () => { + it('can subscribe', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), }; - const query = new ParseQuery("Test"); - query.equalTo("key", "value"); + const query = new ParseQuery('Test'); + query.equalTo('key', 'value'); const subscribePromise = liveQueryClient.subscribe(query); const clientSub = liveQueryClient.subscriptions.get(1); @@ -763,63 +761,63 @@ describe("LiveQueryClient", () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "subscribe", + op: 'subscribe', requestId: 1, query: { - className: "Test", + className: 'Test', where: { - key: "value", + key: 'value', }, }, }); }); - it("can subscribe with sessionToken", async () => { + it('can subscribe with sessionToken', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), }; - const query = new ParseQuery("Test"); - query.equalTo("key", "value"); + const query = new ParseQuery('Test'); + query.equalTo('key', 'value'); - const subscribePromise = liveQueryClient.subscribe(query, "mySessionToken"); + const subscribePromise = liveQueryClient.subscribe(query, 'mySessionToken'); const clientSub = liveQueryClient.subscriptions.get(1); clientSub.subscribePromise.resolve(); const subscription = await subscribePromise; liveQueryClient.connectPromise.resolve(); expect(subscription).toBe(clientSub); - expect(subscription.sessionToken).toBe("mySessionToken"); + expect(subscription.sessionToken).toBe('mySessionToken'); expect(liveQueryClient.requestId).toBe(2); await liveQueryClient.connectPromise; const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "subscribe", + op: 'subscribe', requestId: 1, - sessionToken: "mySessionToken", + sessionToken: 'mySessionToken', query: { - className: "Test", + className: 'Test', where: { - key: "value", + key: 'value', }, }, }); }); - it("can unsubscribe", async () => { + it('can unsubscribe', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), @@ -836,18 +834,18 @@ describe("LiveQueryClient", () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "unsubscribe", + op: 'unsubscribe', requestId: 1, }); }); - it("can unsubscribe without subscription", async () => { + it('can unsubscribe without subscription', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), @@ -858,19 +856,19 @@ describe("LiveQueryClient", () => { expect(liveQueryClient.socket.send).toHaveBeenCalledTimes(0); }); - it("can resubscribe", async () => { + it('can resubscribe', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), }; - const query = new ParseQuery("Test"); - query.equalTo("key", "value"); + const query = new ParseQuery('Test'); + query.equalTo('key', 'value'); liveQueryClient.subscribe(query); liveQueryClient.connectPromise.resolve(); @@ -881,31 +879,31 @@ describe("LiveQueryClient", () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "subscribe", + op: 'subscribe', requestId: 1, query: { - className: "Test", + className: 'Test', where: { - key: "value", + key: 'value', }, }, }); }); - it("can resubscribe with sessionToken", async () => { + it('can resubscribe with sessionToken', async () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); liveQueryClient.socket = { send: jest.fn(), }; - const query = new ParseQuery("Test"); - query.equalTo("key", "value"); - liveQueryClient.subscribe(query, "mySessionToken"); + const query = new ParseQuery('Test'); + query.equalTo('key', 'value'); + liveQueryClient.subscribe(query, 'mySessionToken'); liveQueryClient.connectPromise.resolve(); liveQueryClient.resubscribe(); @@ -915,27 +913,27 @@ describe("LiveQueryClient", () => { const messageStr = liveQueryClient.socket.send.mock.calls[0][0]; const message = JSON.parse(messageStr); expect(message).toEqual({ - op: "subscribe", + op: 'subscribe', requestId: 1, - sessionToken: "mySessionToken", + sessionToken: 'mySessionToken', query: { - className: "Test", + className: 'Test', where: { - key: "value", + key: 'value', }, }, }); }); - it("can close", () => { + it('can close', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); - liveQueryClient.state = "connected"; + liveQueryClient.state = 'connected'; liveQueryClient.socket = { close: jest.fn(), }; @@ -943,11 +941,11 @@ describe("LiveQueryClient", () => { 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; }); @@ -957,27 +955,27 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); expect(isCheckedAgain).toBe(true); expect(liveQueryClient.socket.close).toBeCalled(); - expect(liveQueryClient.state).toBe("disconnected"); + expect(liveQueryClient.state).toBe('disconnected'); }); - it("can handle WebSocket subclass", () => { - const MyExtendedClass = ParseObject.extend("MyExtendedClass"); - ParseObject.registerSubclass("MyExtendedClass", MyExtendedClass); + it('can handle WebSocket subclass', () => { + const MyExtendedClass = ParseObject.extend('MyExtendedClass'); + ParseObject.registerSubclass('MyExtendedClass', MyExtendedClass); const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", - sessionToken: "sessionToken", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); const object = new MyExtendedClass(); - object.set("key", "value"); + object.set('key', 'value'); const data = { - op: "create", + op: 'create', clientId: 1, requestId: 1, object: object._toFullJSON(), @@ -987,12 +985,12 @@ describe("LiveQueryClient", () => { }; // 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"); - expect(parseObject.get("className")).toBeUndefined(); - expect(parseObject.get("__type")).toBeUndefined(); + expect(parseObject.get('key')).toEqual('value'); + expect(parseObject.get('className')).toBeUndefined(); + expect(parseObject.get('__type')).toBeUndefined(); }); liveQueryClient._handleWebSocketMessage(event); @@ -1000,12 +998,12 @@ describe("LiveQueryClient", () => { expect(isChecked).toBe(true); }); - it("cannot subscribe without query", () => { + it('cannot subscribe without query', () => { const liveQueryClient = new LiveQueryClient({ - applicationId: "applicationId", - serverURL: "ws://test", - javascriptKey: "javascriptKey", - masterKey: "masterKey", + applicationId: 'applicationId', + serverURL: 'ws://test', + javascriptKey: 'javascriptKey', + masterKey: 'masterKey', }); const subscription = liveQueryClient.subscribe(); expect(subscription).toBe(undefined); diff --git a/src/__tests__/LocalDatastore-test.js b/src/__tests__/LocalDatastore-test.js index df888b90c..7dce00212 100644 --- a/src/__tests__/LocalDatastore-test.js +++ b/src/__tests__/LocalDatastore-test.js @@ -9,9 +9,9 @@ /* global window */ jest.autoMockOff(); -jest.unmock("../LocalDatastoreUtils"); +jest.unmock('../LocalDatastoreUtils'); -const encode = require("../encode").default; +const encode = require('../encode').default; let objectCount = 0; @@ -32,14 +32,14 @@ class MockObject { } toPointer() { - return "POINTER"; + return 'POINTER'; } dirty() {} _toFullJSON() { const json = { - __type: "Object", + __type: 'Object', className: this.className, }; for (const attr in this.attributes) { @@ -59,7 +59,7 @@ class MockObject { const o = new MockObject(json.className); o.id = json.objectId; for (const attr in json) { - if (attr !== "className" && attr !== "__type" && attr !== "objectId") { + if (attr !== 'className' && attr !== '__type' && attr !== 'objectId') { o.attributes[attr] = json[attr]; } } @@ -75,7 +75,7 @@ class MockObject { } } -const mockAsyncStorage = require("./test_helpers/mockRNStorage"); +const mockAsyncStorage = require('./test_helpers/mockRNStorage'); const mockLocalStorageController = { fromPinWithName: jest.fn(), pinWithName: jest.fn(), @@ -83,10 +83,10 @@ const mockLocalStorageController = { getAllContents: jest.fn(), clear: jest.fn(), }; -jest.setMock("../ParseObject", MockObject); +jest.setMock('../ParseObject', MockObject); const mockQueryFind = jest.fn(); -jest.mock("../ParseQuery", () => { +jest.mock('../ParseQuery', () => { return jest.fn().mockImplementation(function () { this.equalTo = jest.fn(); this.containedIn = jest.fn(); @@ -95,23 +95,23 @@ jest.mock("../ParseQuery", () => { }); }); -const CoreManager = require("../CoreManager"); -const LocalDatastore = require("../LocalDatastore"); -const ParseObject = require("../ParseObject"); -const ParseQuery = require("../ParseQuery"); -const ParseUser = require("../ParseUser").default; -const LocalDatastoreController = require("../LocalDatastoreController"); -const RNDatastoreController = require("../LocalDatastoreController.react-native"); -const BrowserStorageController = require("../StorageController.browser"); -const DefaultStorageController = require("../StorageController.default"); +const CoreManager = require('../CoreManager'); +const LocalDatastore = require('../LocalDatastore'); +const ParseObject = require('../ParseObject'); +const ParseQuery = require('../ParseQuery'); +const ParseUser = require('../ParseUser').default; +const LocalDatastoreController = require('../LocalDatastoreController'); +const RNDatastoreController = require('../LocalDatastoreController.react-native'); +const BrowserStorageController = require('../StorageController.browser'); +const DefaultStorageController = require('../StorageController.default'); -const item1 = new ParseObject("Item"); -const item2 = new ParseObject("Item"); -const item3 = new ParseObject("Item"); +const item1 = new ParseObject('Item'); +const item2 = new ParseObject('Item'); +const item3 = new ParseObject('Item'); -item1.id = "1"; -item2.id = "2"; -item3.id = "3"; +item1.id = '1'; +item2.id = '2'; +item3.id = '3'; const KEY1 = LocalDatastore.getKeyForObject(item1); const KEY2 = LocalDatastore.getKeyForObject(item2); @@ -122,175 +122,164 @@ import { PIN_PREFIX, OBJECT_PREFIX, isLocalDatastoreKey, -} from "../LocalDatastoreUtils"; +} from '../LocalDatastoreUtils'; -describe("LocalDatastore", () => { +describe('LocalDatastore', () => { beforeEach(() => { CoreManager.setLocalDatastoreController(mockLocalStorageController); jest.clearAllMocks(); LocalDatastore.isEnabled = true; }); - it("isEnabled", () => { + it('isEnabled', () => { LocalDatastore.isEnabled = true; const isEnabled = LocalDatastore.checkIfEnabled(); expect(isEnabled).toBe(true); }); - it("isDisabled", () => { - const spy = jest.spyOn(console, "error").mockImplementationOnce(() => {}); + it('isDisabled', () => { + const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {}); LocalDatastore.isEnabled = false; const isEnabled = LocalDatastore.checkIfEnabled(); expect(isEnabled).toBe(false); - LocalDatastore._updateLocalIdForObject("", null); + LocalDatastore._updateLocalIdForObject('', null); LocalDatastore._destroyObjectIfPinned(null); LocalDatastore._updateObjectIfPinned(null); - expect(spy).toHaveBeenCalledWith( - "Parse.enableLocalDatastore() must be called first" - ); + expect(spy).toHaveBeenCalledWith('Parse.enableLocalDatastore() must be called first'); spy.mockRestore(); }); - it("can clear", async () => { + it('can clear', async () => { await LocalDatastore._clear(); expect(mockLocalStorageController.clear).toHaveBeenCalledTimes(1); }); - it("can getAllContents", async () => { + it('can getAllContents', async () => { await LocalDatastore._getAllContents(); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_handlePinAllWithName no children", async () => { - const object = new ParseObject("Item"); - await LocalDatastore._handlePinAllWithName("test_pin", [object]); + it('_handlePinAllWithName no children', async () => { + const object = new ParseObject('Item'); + await LocalDatastore._handlePinAllWithName('test_pin', [object]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it("_handlePinAllWithName with localId", async () => { - const object = new ParseObject("Item"); - object._localId = "local0"; + it('_handlePinAllWithName with localId', async () => { + const object = new ParseObject('Item'); + object._localId = 'local0'; object.id = null; - await LocalDatastore._handlePinAllWithName("test_pin", [object]); + await LocalDatastore._handlePinAllWithName('test_pin', [object]); expect(mockLocalStorageController.pinWithName.mock.calls[0][0]).toEqual( - "Parse_LDS_Item_local0" + 'Parse_LDS_Item_local0' ); expect(mockLocalStorageController.pinWithName.mock.calls[0][1]).toEqual([ - { __type: "Object", className: "Item", _localId: "local0" }, + { __type: 'Object', className: 'Item', _localId: 'local0' }, ]); }); - it("_handlePinAllWithName default pin", async () => { - const object = new ParseObject("Item"); + it('_handlePinAllWithName default pin', async () => { + const object = new ParseObject('Item'); await LocalDatastore._handlePinAllWithName(DEFAULT_PIN, [object]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it("_handlePinAllWithName unsaved children", async () => { - const parent = new ParseObject("Item"); - const unsaved = { className: "Item", __type: "Object" }; - parent.set("child", unsaved); - await LocalDatastore._handlePinAllWithName("test_pin", [parent]); + it('_handlePinAllWithName unsaved children', async () => { + const parent = new ParseObject('Item'); + const unsaved = { className: 'Item', __type: 'Object' }; + parent.set('child', unsaved); + await LocalDatastore._handlePinAllWithName('test_pin', [parent]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it("_handlePinAllWithName with children", async () => { - const parent = new ParseObject("Item"); - const child = new ParseObject("Item"); - const grandchild = new ParseObject("Item"); - child.set("grandchild", grandchild); - parent.set("child", child); - await LocalDatastore._handlePinAllWithName("test_pin", [parent]); + it('_handlePinAllWithName with children', async () => { + const parent = new ParseObject('Item'); + const child = new ParseObject('Item'); + const grandchild = new ParseObject('Item'); + child.set('grandchild', grandchild); + parent.set('child', child); + await LocalDatastore._handlePinAllWithName('test_pin', [parent]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(4); }); - it("_handleUnPinAllWithName default pin", async () => { + it('_handleUnPinAllWithName default pin', async () => { const LDS = { [DEFAULT_PIN]: [KEY1, KEY2], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName(DEFAULT_PIN, [item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalStorageController.pinWithName - ).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); }); - it("_handleUnPinAllWithName specific pin", async () => { + it('_handleUnPinAllWithName specific pin', async () => { const LDS = { parsePin_test_pin: [KEY1, KEY2], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - await LocalDatastore._handleUnPinAllWithName("test_pin", [item1]); + 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 () => { - const object = new ParseObject("Item"); + it('_handleUnPinAllWithName default pin remove pinName', async () => { + const object = new ParseObject('Item'); const LDS = { [DEFAULT_PIN]: [], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName(DEFAULT_PIN, [object]); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(2); - expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( - DEFAULT_PIN - ); + expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(DEFAULT_PIN); }); - it("_handleUnPinAllWithName specific pin remove pinName", async () => { - const object = new ParseObject("Item"); + it('_handleUnPinAllWithName specific pin remove pinName', async () => { + const object = new ParseObject('Item'); const LDS = { - [PIN_PREFIX + "test_pin"]: [], + [PIN_PREFIX + 'test_pin']: [], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - await LocalDatastore._handleUnPinAllWithName("test_pin", [object]); + await LocalDatastore._handleUnPinAllWithName('test_pin', [object]); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(2); - expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( - PIN_PREFIX + "test_pin" - ); + expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin'); }); - it("_handleUnPinAllWithName remove if exist", async () => { + it('_handleUnPinAllWithName remove if exist', async () => { const objects = [KEY1, KEY2, KEY3]; const LDS = { - [PIN_PREFIX + "test_pin"]: objects, - [PIN_PREFIX + "test_pin_2"]: objects, + [PIN_PREFIX + 'test_pin']: objects, + [PIN_PREFIX + 'test_pin_2']: objects, [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - await LocalDatastore._handleUnPinAllWithName("test_pin", [item1]); + 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 () => { - const object = new ParseObject("Item"); + it('_updateObjectIfPinned not pinned', async () => { + const object = new ParseObject('Item'); LocalDatastore.isEnabled = true; LocalDatastore._updateObjectIfPinned(object); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it("_updateObjectIfPinned if pinned", async () => { - mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => [ - item1, - ]); + it('_updateObjectIfPinned if pinned', async () => { + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => [item1]); LocalDatastore.isEnabled = true; await LocalDatastore._updateObjectIfPinned(item1); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalStorageController.fromPinWithName.mock.results[0].value - ).toEqual([item1]); + expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual([item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(KEY1, [ @@ -298,25 +287,21 @@ describe("LocalDatastore", () => { ]); }); - it("_updateLocalIdForObject not pinned", async () => { - await LocalDatastore._updateLocalIdForObject("local0", item1); - expect( - mockLocalStorageController.fromPinWithName.mock.results[0].value - ).toEqual(undefined); + it('_updateLocalIdForObject not pinned', async () => { + await LocalDatastore._updateLocalIdForObject('local0', item1); + expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual(undefined); }); - it("_updateLocalIdForObject if pinned", async () => { - const object = new ParseObject("Item"); + it('_updateLocalIdForObject if pinned', async () => { + const object = new ParseObject('Item'); const json = object._toFullJSON(); - const localId = "local" + object.id; + const localId = 'local' + object.id; const localKey = `${OBJECT_PREFIX}Item_${localId}`; const LDS = { [DEFAULT_PIN]: [localKey], [localKey]: [json], }; - mockLocalStorageController.fromPinWithName.mockImplementationOnce( - () => json - ); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); @@ -324,18 +309,16 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it("_updateLocalIdForObject if pinned with name", async () => { - const object = new ParseObject("Item"); + it('_updateLocalIdForObject if pinned with name', async () => { + const object = new ParseObject('Item'); const json = object._toFullJSON(); - const localId = "local" + object.id; + const localId = 'local' + object.id; const localKey = `${OBJECT_PREFIX}Item_${localId}`; const LDS = { - [PIN_PREFIX + "test_pin"]: [localKey], + [PIN_PREFIX + 'test_pin']: [localKey], [localKey]: [json], }; - mockLocalStorageController.fromPinWithName.mockImplementationOnce( - () => json - ); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); @@ -343,26 +326,22 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); }); - it("_updateLocalIdForObject if pinned with new name", async () => { - const object = new ParseObject("Item"); + it('_updateLocalIdForObject if pinned with new name', async () => { + const object = new ParseObject('Item'); const json = object._toFullJSON(); - const localId = "local" + object.id; + const localId = 'local' + object.id; const LDS = { [DEFAULT_PIN]: [object.id], [object.id]: [json], }; - mockLocalStorageController.fromPinWithName.mockImplementationOnce( - () => json - ); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._updateLocalIdForObject(localId, object); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalStorageController.fromPinWithName.mock.results[0].value - ).toEqual(json); + expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual(json); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( @@ -378,7 +357,7 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_serializeObjectsFromPinName no name returns all objects", async () => { + it('_serializeObjectsFromPinName no name returns all objects', async () => { const json = item1._toFullJSON(); const LDS = { [DEFAULT_PIN]: [KEY1], @@ -393,35 +372,33 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_serializeObjectsFromPinName no objects", async () => { - const object = new ParseObject("Item"); + it('_serializeObjectsFromPinName no objects', async () => { + const object = new ParseObject('Item'); const json = object._toFullJSON(); const LDS = { - [DEFAULT_PIN]: [object.id, "local10", "local11"], + [DEFAULT_PIN]: [object.id, 'local10', 'local11'], [object.id]: [json], randomName: [object.id], }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - const results = await LocalDatastore._serializeObjectsFromPinName( - DEFAULT_PIN - ); + const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); expect(results).toEqual([]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_serializeObjectsFromPinName with name", async () => { - const obj1 = new ParseObject("Item"); - const obj2 = new ParseObject("Item"); - const obj3 = new ParseObject("Item"); + it('_serializeObjectsFromPinName with name', async () => { + const obj1 = new ParseObject('Item'); + const obj2 = new ParseObject('Item'); + const obj3 = new ParseObject('Item'); const LDS = { [obj1.id]: [obj1._toFullJSON()], [obj2.id]: [obj2._toFullJSON()], [obj3.id]: [obj3._toFullJSON()], - [PIN_PREFIX + "testPin"]: [obj1.id, obj2.id, obj3.id], + [PIN_PREFIX + 'testPin']: [obj1.id, obj2.id, obj3.id], }; mockLocalStorageController.fromPinWithName @@ -431,36 +408,28 @@ describe("LocalDatastore", () => { mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - const results = await LocalDatastore._serializeObjectsFromPinName( - "testPin" - ); - expect(results).toEqual([ - obj1._toFullJSON(), - obj2._toFullJSON(), - obj3._toFullJSON(), - ]); + const results = await LocalDatastore._serializeObjectsFromPinName('testPin'); + expect(results).toEqual([obj1._toFullJSON(), obj2._toFullJSON(), obj3._toFullJSON()]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.fromPinWithName).toHaveBeenCalledTimes(3); }); - it("_serializeObjectsFromPinName null pin", async () => { + it('_serializeObjectsFromPinName null pin', async () => { const LDS = { [DEFAULT_PIN]: null, }; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - const results = await LocalDatastore._serializeObjectsFromPinName( - DEFAULT_PIN - ); + const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); expect(results).toEqual([]); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_serializeObject no children", async () => { - const object = new ParseObject("Item"); + it('_serializeObject no children', async () => { + const object = new ParseObject('Item'); object.id = 1234; const json = object._toFullJSON(); const objectKey = `Item_1234`; @@ -477,8 +446,8 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); - it("_serializeObject object does not exist", async () => { - const object = new ParseObject("Item"); + it('_serializeObject object does not exist', async () => { + const object = new ParseObject('Item'); object.id = 1234; const objectKey = `Item_1234`; const LDS = {}; @@ -489,14 +458,14 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it("_serializeObject with children", async () => { - const parent = new ParseObject("Item"); + it('_serializeObject with children', async () => { + const parent = new ParseObject('Item'); parent.id = 1234; - const child = new ParseObject("Item"); + const child = new ParseObject('Item'); child.id = 5678; - parent.set("child", child); + parent.set('child', child); const childJSON = child._toFullJSON(); - childJSON.field = "Serialize Me"; + childJSON.field = 'Serialize Me'; const parentKey = LocalDatastore.getKeyForObject(parent); const childKey = LocalDatastore.getKeyForObject(child); @@ -514,7 +483,7 @@ describe("LocalDatastore", () => { expect(result).toEqual(expectedResults); }); - it("_destroyObjectIfPinned no objects found in pinName", async () => { + it('_destroyObjectIfPinned no objects found in pinName', async () => { let LDS = {}; LocalDatastore.isEnabled = true; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); @@ -542,11 +511,11 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it("_destroyObjectIfPinned no objects found in pinName remove pinName", async () => { + it('_destroyObjectIfPinned no objects found in pinName remove pinName', async () => { const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], - [PIN_PREFIX + "Custom_Pin"]: [KEY2], + [PIN_PREFIX + 'Custom_Pin']: [KEY2], [DEFAULT_PIN]: [KEY2], }; @@ -561,7 +530,7 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it("_destroyObjectIfPinned", async () => { + it('_destroyObjectIfPinned', async () => { const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], @@ -577,12 +546,10 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(KEY1); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalStorageController.pinWithName - ).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); }); - it("_traverse", () => { + it('_traverse', () => { // Skip if no objectId const json = item1._toFullJSON(); let encountered = {}; @@ -600,47 +567,47 @@ describe("LocalDatastore", () => { expect(encountered).toEqual({ [KEY1]: json }); // Test if null field exist still encounter - const object = { objectId: 1234, className: "Item", field: null }; + const object = { objectId: 1234, className: 'Item', field: null }; encountered = {}; LocalDatastore._traverse(object, encountered); expect(encountered).toEqual({ [`${OBJECT_PREFIX}Item_1234`]: object }); }); - it("do not sync if disabled", async () => { + it('do not sync if disabled', async () => { LocalDatastore.isEnabled = false; - jest.spyOn(console, "error").mockImplementationOnce(() => {}); - jest.spyOn(mockLocalStorageController, "getAllContents"); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); + jest.spyOn(mockLocalStorageController, 'getAllContents'); await LocalDatastore.updateFromServer(); expect(LocalDatastore.isSyncing).toBe(false); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it("do not sync if syncing", async () => { + it('do not sync if syncing', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = true; - jest.spyOn(mockLocalStorageController, "getAllContents"); + jest.spyOn(mockLocalStorageController, 'getAllContents'); await LocalDatastore.updateFromServer(); expect(LocalDatastore.isSyncing).toBe(true); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(0); }); - it("updateFromServer empty LDS", async () => { + it('updateFromServer empty LDS', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = {}; mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - jest.spyOn(mockLocalStorageController, "pinWithName"); + jest.spyOn(mockLocalStorageController, 'pinWithName'); await LocalDatastore.updateFromServer(); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(0); }); - it("updateFromServer on one object", async () => { + it('updateFromServer on one object', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = { @@ -651,7 +618,7 @@ describe("LocalDatastore", () => { mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - item1.set("updatedField", "foo"); + item1.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); await LocalDatastore.updateFromServer(); @@ -665,12 +632,12 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it("updateFromServer on user", async () => { + it('updateFromServer on user', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const user = new ParseUser(); - user.id = "1234"; + user.id = '1234'; user._localId = null; const USER_KEY = LocalDatastore.getKeyForObject(user); @@ -682,7 +649,7 @@ describe("LocalDatastore", () => { mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - user.set("updatedField", "foo"); + user.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([user])); await LocalDatastore.updateFromServer(); @@ -696,12 +663,12 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it("updateFromServer ignore unsaved objects", async () => { + it('updateFromServer ignore unsaved objects', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; - const object = new ParseObject("Item"); - object._localId = "local0"; + const object = new ParseObject('Item'); + object._localId = 'local0'; object.id = null; const OBJECT_KEY = LocalDatastore.getKeyForObject(object); @@ -714,7 +681,7 @@ describe("LocalDatastore", () => { mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); - item1.set("updatedField", "foo"); + item1.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); await LocalDatastore.updateFromServer(); @@ -728,7 +695,7 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); }); - it("updateFromServer handle error", async () => { + it('updateFromServer handle error', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; const LDS = { @@ -741,10 +708,10 @@ describe("LocalDatastore", () => { mockQueryFind.mockImplementationOnce(() => { expect(LocalDatastore.isSyncing).toBe(true); - return Promise.reject("Unable to connect to the Parse API"); + return Promise.reject('Unable to connect to the Parse API'); }); - jest.spyOn(console, "error").mockImplementationOnce(() => {}); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); await LocalDatastore.updateFromServer(); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); @@ -758,10 +725,10 @@ describe("LocalDatastore", () => { expect(LocalDatastore.isSyncing).toBe(false); }); - it("updateFromServer on mixed object", async () => { + it('updateFromServer on mixed object', async () => { LocalDatastore.isEnabled = true; LocalDatastore.isSyncing = false; - const testObject = new ParseObject("TestObject"); + const testObject = new ParseObject('TestObject'); const LDS = { [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], @@ -790,28 +757,26 @@ describe("LocalDatastore", () => { expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(3); }); - it("isLocalDatastoreKey", () => { + it('isLocalDatastoreKey', () => { expect(isLocalDatastoreKey(null)).toBe(false); - expect(isLocalDatastoreKey("")).toBe(false); + expect(isLocalDatastoreKey('')).toBe(false); expect(isLocalDatastoreKey(DEFAULT_PIN)).toBe(true); expect(isLocalDatastoreKey(PIN_PREFIX)).toBe(true); expect(isLocalDatastoreKey(OBJECT_PREFIX)).toBe(true); }); }); -describe("LocalDatastore (BrowserStorageController)", () => { +describe('LocalDatastore (BrowserStorageController)', () => { beforeEach(async () => { CoreManager.setStorageController(BrowserStorageController); CoreManager.setLocalDatastoreController(LocalDatastoreController); await LocalDatastore._clear(); }); - it("can store and retrieve values", async () => { + it('can store and retrieve values', async () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()], }); @@ -820,25 +785,23 @@ describe("LocalDatastore (BrowserStorageController)", () => { }); }); - it("can remove values", async () => { + it('can remove values', async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); expect(await LocalDatastore._getRawStorage()).toEqual({}); }); - it("can handle getAllContent error", async () => { - await LocalDatastore.pinWithName("_default", [{ value: "WILL_BE_MOCKED" }]); + it('can handle getAllContent error', async () => { + await LocalDatastore.pinWithName('_default', [{ value: 'WILL_BE_MOCKED' }]); const windowSpy = jest - .spyOn(Object.getPrototypeOf(window.localStorage), "getItem") + .spyOn(Object.getPrototypeOf(window.localStorage), 'getItem') .mockImplementationOnce(() => { - return "[1, ]"; + return '[1, ]'; }); - const spy = jest.spyOn(console, "error").mockImplementationOnce(() => {}); + const spy = jest.spyOn(console, 'error').mockImplementationOnce(() => {}); const LDS = await LocalDatastore._getAllContents(); expect(LDS).toEqual({}); expect(spy).toHaveBeenCalled(); @@ -846,35 +809,31 @@ describe("LocalDatastore (BrowserStorageController)", () => { windowSpy.mockRestore(); }); - it("can handle store error", async () => { + it('can handle store error', async () => { const windowSpy = jest - .spyOn(Object.getPrototypeOf(window.localStorage), "setItem") + .spyOn(Object.getPrototypeOf(window.localStorage), 'setItem') .mockImplementationOnce(() => { - throw new Error("error thrown"); + throw new Error('error thrown'); }); - const consoleSpy = jest - .spyOn(console, "log") - .mockImplementationOnce(() => {}); - await LocalDatastore.pinWithName("myKey", [{ name: "test" }]); + const consoleSpy = jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + await LocalDatastore.pinWithName('myKey', [{ name: 'test' }]); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); windowSpy.mockRestore(); }); }); -describe("LocalDatastore (DefaultStorageController)", () => { +describe('LocalDatastore (DefaultStorageController)', () => { beforeEach(async () => { CoreManager.setStorageController(DefaultStorageController); CoreManager.setLocalDatastoreController(LocalDatastoreController); await LocalDatastore._clear(); }); - it("can store and retrieve values", async () => { + it('can store and retrieve values', async () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()], }); @@ -883,11 +842,9 @@ describe("LocalDatastore (DefaultStorageController)", () => { }); }); - it("can remove values", async () => { + it('can remove values', async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); @@ -895,19 +852,17 @@ describe("LocalDatastore (DefaultStorageController)", () => { }); }); -describe("LocalDatastore (RNDatastoreController)", () => { +describe('LocalDatastore (RNDatastoreController)', () => { beforeEach(async () => { CoreManager.setAsyncStorage(mockAsyncStorage); CoreManager.setLocalDatastoreController(RNDatastoreController); await LocalDatastore._clear(); }); - it("can store and retrieve values", async () => { + it('can store and retrieve values', async () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()], }); @@ -916,70 +871,68 @@ describe("LocalDatastore (RNDatastoreController)", () => { }); }); - it("can remove values", async () => { + it('can remove values', async () => { await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); - expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([ - item1._toFullJSON(), - ]); + expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); await LocalDatastore.unPinWithName(KEY1); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); expect(await LocalDatastore._getAllContents()).toEqual({}); expect(await LocalDatastore._getRawStorage()).toEqual({}); }); - it("can handle store error", async () => { + it('can handle store error', async () => { const mockStorageError = { setItem() { - throw new Error("error thrown"); + throw new Error('error thrown'); }, }; - jest.spyOn(console, "error").mockImplementationOnce(() => {}); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); try { - await LocalDatastore.pinWithName("myKey", [{ name: "test" }]); + await LocalDatastore.pinWithName('myKey', [{ name: 'test' }]); } catch (e) { - expect(e.message).toBe("error thrown"); + expect(e.message).toBe('error thrown'); } }); - it("can handle getAllContents undefined", async () => { + it('can handle getAllContents undefined', async () => { await RNDatastoreController.pinWithName(KEY1, undefined); const contents = await RNDatastoreController.getAllContents(); expect(contents[KEY1]).toEqual(null); }); - it("can handle getAllContents non-LDS object", async () => { + it('can handle getAllContents non-LDS object', async () => { await RNDatastoreController.pinWithName(KEY1, item1._toFullJSON()); - await RNDatastoreController.pinWithName("DO_NOT_FETCH", undefined); + await RNDatastoreController.pinWithName('DO_NOT_FETCH', undefined); const contents = await RNDatastoreController.getAllContents(); expect(contents[KEY1]).toEqual(item1._toFullJSON()); - expect(contents["DO_NOT_FETCH"]).toBeUndefined(); + expect(contents['DO_NOT_FETCH']).toBeUndefined(); }); - it("can handle clear error", async () => { + it('can handle clear error', async () => { const mockStorageError = { multiRemove(keys, cb) { - cb("error thrown"); + cb('error thrown'); }, getAllKeys(cb) { - cb(undefined, [KEY1, "DO_NOT_CLEAR"]); + cb(undefined, [KEY1, 'DO_NOT_CLEAR']); }, }; - jest.spyOn(console, "error").mockImplementationOnce(() => {}); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); await LocalDatastore._clear(); }); - it("can handle multiget error", async () => { + it('can handle multiget error', async () => { const mockStorageError = { multiGet(keys, cb) { - cb("error thrown"); + cb('error thrown'); }, getAllKeys(cb) { - cb(undefined, [KEY1, "DO_NOT_CLEAR"]); + cb(undefined, [KEY1, 'DO_NOT_CLEAR']); }, }; - jest.spyOn(console, "error").mockImplementationOnce(() => {}); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); const LDS = await LocalDatastore._getAllContents(); expect(LDS).toEqual({}); diff --git a/src/__tests__/ObjectStateMutations-test.js b/src/__tests__/ObjectStateMutations-test.js index d5b315ac3..08c750719 100644 --- a/src/__tests__/ObjectStateMutations-test.js +++ b/src/__tests__/ObjectStateMutations-test.js @@ -7,27 +7,27 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParseRelation"); -jest.dontMock("../TaskQueue"); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParseRelation'); +jest.dontMock('../TaskQueue'); const mockObject = function (className) { this.className = className; }; mockObject.registerSubclass = function () {}; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const ObjectStateMutations = require("../ObjectStateMutations"); -const ParseOps = require("../ParseOp"); -const TaskQueue = require("../TaskQueue"); +const ObjectStateMutations = require('../ObjectStateMutations'); +const ParseOps = require('../ParseOp'); +const TaskQueue = require('../TaskQueue'); -describe("ObjectStateMutations", () => { - it("can apply server data", () => { +describe('ObjectStateMutations', () => { + it('can apply server data', () => { const serverData = {}; ObjectStateMutations.setServerData(serverData, { counter: 12 }); expect(serverData).toEqual({ counter: 12 }); @@ -35,21 +35,21 @@ describe("ObjectStateMutations", () => { expect(serverData).toEqual({}); }); - it("can set a pending op", () => { + it('can set a pending op', () => { let pendingOps = [{}]; const op = new ParseOps.IncrementOp(1); - ObjectStateMutations.setPendingOp(pendingOps, "counter", op); + ObjectStateMutations.setPendingOp(pendingOps, 'counter', op); expect(pendingOps).toEqual([{ counter: op }]); pendingOps = [{}, {}]; - ObjectStateMutations.setPendingOp(pendingOps, "counter", op); + ObjectStateMutations.setPendingOp(pendingOps, 'counter', op); expect(pendingOps).toEqual([{}, { counter: op }]); - ObjectStateMutations.setPendingOp(pendingOps, "counter", null); + ObjectStateMutations.setPendingOp(pendingOps, 'counter', null); expect(pendingOps).toEqual([{}, {}]); }); - it("can push a new pending state", () => { + it('can push a new pending state', () => { const pendingOps = [{}]; ObjectStateMutations.pushPendingState(pendingOps); expect(pendingOps).toEqual([{}, {}]); @@ -58,7 +58,7 @@ describe("ObjectStateMutations", () => { expect(pendingOps).toEqual([{}, {}, {}]); }); - it("can pop a pending state", () => { + it('can pop a pending state', () => { let pendingOps = [{}]; let first = pendingOps[0]; expect(ObjectStateMutations.popPendingState(pendingOps)).toBe(first); @@ -71,173 +71,131 @@ describe("ObjectStateMutations", () => { expect(pendingOps).toEqual([{}, {}]); }); - it("can merge the first op set into the next", () => { - let pendingOps = [ - { counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp("foo") }, - {}, - ]; + 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") }, + { 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) }]); }); - it("can estimate an attribute value", () => { + it('can estimate an attribute value', () => { const serverData = { counter: 12 }; - const pendingOps = [ - { counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp("foo") }, - ]; + const pendingOps = [{ counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp('foo') }]; expect( ObjectStateMutations.estimateAttribute( serverData, pendingOps, - "someClass", - "someId", - "counter" + 'someClass', + 'someId', + 'counter' ) ).toBe(14); expect( - ObjectStateMutations.estimateAttribute( - serverData, - pendingOps, - "someClass", - "someId", - "name" - ) - ).toBe("foo"); + ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name') + ).toBe('foo'); pendingOps.push({ counter: new ParseOps.IncrementOp(1), - name: new ParseOps.SetOp("override"), + name: new ParseOps.SetOp('override'), }); expect( ObjectStateMutations.estimateAttribute( serverData, pendingOps, - "someClass", - "someId", - "counter" + 'someClass', + 'someId', + 'counter' ) ).toBe(15); expect( - ObjectStateMutations.estimateAttribute( - serverData, - pendingOps, - "someClass", - "someId", - "name" - ) - ).toBe("override"); + ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name') + ).toBe('override'); pendingOps.push({ likes: new ParseOps.RelationOp([], []) }); const relation = ObjectStateMutations.estimateAttribute( serverData, pendingOps, - "someClass", - "someId", - "likes" + 'someClass', + 'someId', + 'likes' ); - expect(relation.parent.id).toBe("someId"); - expect(relation.parent.className).toBe("someClass"); - expect(relation.key).toBe("likes"); + expect(relation.parent.id).toBe('someId'); + expect(relation.parent.className).toBe('someClass'); + expect(relation.key).toBe('likes'); }); - it("can estimate all attributes", () => { + it('can estimate all attributes', () => { const serverData = { counter: 12 }; - const pendingOps = [ - { counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp("foo") }, - ]; + const pendingOps = [{ counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp('foo') }]; expect( - ObjectStateMutations.estimateAttributes( - serverData, - pendingOps, - "someClass", - "someId" - ) + 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"), + name: new ParseOps.SetOp('override'), }); expect( - ObjectStateMutations.estimateAttributes( - serverData, - pendingOps, - "someClass", - "someId" - ) + 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" + 'someClass', + 'someId' ); - expect(attributes.likes.parent.id).toBe("someId"); - expect(attributes.likes.parent.className).toBe("someClass"); - expect(attributes.likes.key).toBe("likes"); + expect(attributes.likes.parent.id).toBe('someId'); + expect(attributes.likes.parent.className).toBe('someClass'); + expect(attributes.likes.key).toBe('likes'); }); - it("can estimate attributes for nested documents", () => { - const serverData = { objectField: { counter: 10, letter: "a" } }; - let pendingOps = [{ "objectField.counter": new ParseOps.IncrementOp(2) }]; + 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" - ) + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') ).toEqual({ objectField: { counter: 12, - letter: "a", + letter: 'a', }, }); - pendingOps = [{ "objectField.counter": new ParseOps.SetOp(20) }]; + pendingOps = [{ 'objectField.counter': new ParseOps.SetOp(20) }]; expect( - ObjectStateMutations.estimateAttributes( - serverData, - pendingOps, - "someClass", - "someId" - ) + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') ).toEqual({ objectField: { counter: 20, - letter: "a", + letter: 'a', }, }); }); - it("can commit changes from the server", () => { + it('can commit changes from the server', () => { const serverData = {}; const objectCache = {}; ObjectStateMutations.commitServerChanges(serverData, objectCache, { - name: "foo", + name: 'foo', data: { count: 5 }, }); - expect(serverData).toEqual({ name: "foo", data: { count: 5 } }); + expect(serverData).toEqual({ name: 'foo', data: { count: 5 } }); expect(objectCache).toEqual({ data: '{"count":5}' }); }); - it("can generate a default state for implementations", () => { + it('can generate a default state for implementations', () => { expect(ObjectStateMutations.defaultState()).toEqual({ serverData: {}, pendingOps: [{}], diff --git a/src/__tests__/OfflineQuery-test.js b/src/__tests__/OfflineQuery-test.js index ea85e1c2c..5ab209a3d 100644 --- a/src/__tests__/OfflineQuery-test.js +++ b/src/__tests__/OfflineQuery-test.js @@ -9,138 +9,130 @@ jest.autoMockOff(); -const matchesQuery = require("../OfflineQuery").matchesQuery; -const validateQuery = require("../OfflineQuery").validateQuery; -const ParseError = require("../ParseError").default; -const ParseObject = require("../ParseObject").default; -const ParseQuery = require("../ParseQuery").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -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"); +const matchesQuery = require('../OfflineQuery').matchesQuery; +const validateQuery = require('../OfflineQuery').validateQuery; +const ParseError = require('../ParseError').default; +const ParseObject = require('../ParseObject').default; +const ParseQuery = require('../ParseQuery').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +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'); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - expect( - matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where) - ).toBe(true); + expect(matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where)).toBe(true); }); - it("can handle unknown query", () => { - const obj = new ParseObject("Item"); - const q = new ParseQuery("Item"); - q._addCondition("key", "unknown", "value"); + it('can handle unknown query', () => { + const obj = new ParseObject('Item'); + const q = new ParseQuery('Item'); + q._addCondition('key', 'unknown', 'value'); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - expect( - matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where) - ).toBe(false); + expect(matchesQuery(q.className, obj._toFullJSON(), [], q.toJSON().where)).toBe(false); }); - it("matches queries null field", () => { - const obj = new ParseObject("Item"); - const q = new ParseQuery("Item"); - q.equalTo("field", null); + it('matches queries null field', () => { + const obj = new ParseObject('Item'); + const q = new ParseQuery('Item'); + q.equalTo('field', null); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it("matches queries invalid key", () => { - const obj = new ParseObject("Item"); - const q = new ParseQuery("Item"); - q.equalTo("$foo", "bar"); + it('matches queries invalid key', () => { + const obj = new ParseObject('Item'); + const q = new ParseQuery('Item'); + q.equalTo('$foo', 'bar'); try { matchesQuery(q.className, obj, [], q); } catch (e) { - expect(e.message).toBe("Invalid Key: $foo"); + expect(e.message).toBe('Invalid Key: $foo'); } }); - it("matches queries date field", () => { + it('matches queries date field', () => { const date = new Date(); - const obj = new ParseObject("Item"); - obj.set("field", date); - const q = new ParseQuery("Item"); - q.greaterThanOrEqualTo("field", date); + const obj = new ParseObject('Item'); + obj.set('field', date); + const q = new ParseQuery('Item'); + q.greaterThanOrEqualTo('field', date); expect(matchesQuery(q.className, obj, [], q)).toBe(true); }); - it("matches queries relation", () => { - const obj = new ParseObject("Item"); - const relation = obj.relation("author"); + it('matches queries relation', () => { + const obj = new ParseObject('Item'); + const relation = obj.relation('author'); const q = relation.query(); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it("matches existence queries", () => { - const obj = new ParseObject("Item"); - obj.set("count", 100); - const q = new ParseQuery("Item"); - q.exists("count"); + it('matches existence queries', () => { + const obj = new ParseObject('Item'); + obj.set('count', 100); + const q = new ParseQuery('Item'); + q.exists('count'); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.exists("name"); + q.exists('name'); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it("matches queries with doesNotExist constraint", () => { - const obj = new ParseObject("Item"); - obj.set("count", 100); + it('matches queries with doesNotExist constraint', () => { + const obj = new ParseObject('Item'); + obj.set('count', 100); - let q = new ParseQuery("Item"); - q.doesNotExist("name"); + let q = new ParseQuery('Item'); + q.doesNotExist('name'); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery("Item"); - q.doesNotExist("count"); + q = new ParseQuery('Item'); + q.doesNotExist('count'); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); - it("matches on equality queries", () => { + it('matches on equality queries', () => { const day = new Date(); const location = new ParseGeoPoint({ latitude: 37.484815, longitude: -122.148377, }); - const obj = new ParseObject("Person"); - obj - .set("score", 12) - .set("name", "Bill") - .set("birthday", day) - .set("lastLocation", location); - - let q = new ParseQuery("Person"); - q.equalTo("score", 12); + const obj = new ParseObject('Person'); + obj.set('score', 12).set('name', 'Bill').set('birthday', day).set('lastLocation', location); + + let q = new ParseQuery('Person'); + q.equalTo('score', 12); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery("Person"); - q.equalTo("name", "Bill"); + q = new ParseQuery('Person'); + q.equalTo('name', 'Bill'); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo("name", "Jeff"); + q.equalTo('name', 'Jeff'); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q = new ParseQuery("Person"); - q.containedIn("name", ["Adam", "Ben", "Charles"]); + q = new ParseQuery('Person'); + q.containedIn('name', ['Adam', 'Ben', 'Charles']); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q.containedIn("name", ["Adam", "Bill", "Charles"]); + q.containedIn('name', ['Adam', 'Bill', 'Charles']); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery("Person"); - q.notContainedIn("name", ["Adam", "Bill", "Charles"]); + q = new ParseQuery('Person'); + q.notContainedIn('name', ['Adam', 'Bill', 'Charles']); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q.notContainedIn("name", ["Adam", "Ben", "Charles"]); + q.notContainedIn('name', ['Adam', 'Ben', 'Charles']); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q = new ParseQuery("Person"); - q.equalTo("birthday", day); + q = new ParseQuery('Person'); + q.equalTo('birthday', day); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo("birthday", new Date(1990, 1)); + q.equalTo('birthday', new Date(1990, 1)); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q = new ParseQuery("Person"); - q.equalTo("lastLocation", location); + q = new ParseQuery('Person'); + q.equalTo('lastLocation', location); expect(matchesQuery(q.className, obj, [], q)).toBe(true); q.equalTo( - "lastLocation", + 'lastLocation', new ParseGeoPoint({ latitude: 37.4848, longitude: -122.1483, @@ -149,120 +141,117 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, obj, [], q)).toBe(false); q.equalTo( - "lastLocation", + 'lastLocation', new ParseGeoPoint({ latitude: 37.484815, longitude: -122.148377, }) ); - q.equalTo("score", 12); - q.equalTo("name", "Bill"); - q.equalTo("birthday", day); + q.equalTo('score', 12); + q.equalTo('name', 'Bill'); + q.equalTo('birthday', day); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo("name", "bill"); + q.equalTo('name', 'bill'); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - let img = new ParseObject("Image"); - img.set("tags", ["nofilter", "latergram", "tbt"]); + let img = new ParseObject('Image'); + img.set('tags', ['nofilter', 'latergram', 'tbt']); - q = new ParseQuery("Image"); - q.equalTo("tags", "selfie"); + q = new ParseQuery('Image'); + q.equalTo('tags', 'selfie'); expect(matchesQuery(q.className, img, [], q)).toBe(false); - q.equalTo("tags", "tbt"); + q.equalTo('tags', 'tbt'); expect(matchesQuery(q.className, img, [], q)).toBe(true); - const q2 = new ParseQuery("Image"); - q2.containsAll("tags", ["latergram", "nofilter"]); + const q2 = new ParseQuery('Image'); + q2.containsAll('tags', ['latergram', 'nofilter']); expect(matchesQuery(q.className, img, [], q2)).toBe(true); - q2.containsAll("tags", ["latergram", "selfie"]); + q2.containsAll('tags', ['latergram', 'selfie']); expect(matchesQuery(q.className, img, [], q2)).toBe(false); const u = new ParseUser(); - u.id = "U2"; - q = new ParseQuery("Image"); - q.equalTo("owner", u); + u.id = 'U2'; + q = new ParseQuery('Image'); + q.equalTo('owner', u); - img = new ParseObject("Image"); - img.set("owner", u); + img = new ParseObject('Image'); + img.set('owner', u); expect(matchesQuery(q.className, img, [], q)).toBe(true); let json = img.toJSON(); - json.owner.objectId = "U3"; + json.owner.objectId = 'U3'; expect(matchesQuery(json, q)).toBe(false); // pointers in arrays - q = new ParseQuery("Image"); - q.equalTo("owners", u); + q = new ParseQuery('Image'); + q.equalTo('owners', u); - img = new ParseObject("Image"); - img.set("owners", [u]); + img = new ParseObject('Image'); + img.set('owners', [u]); expect(matchesQuery(q.className, img, [], q)).toBe(true); json = img.toJSON(); - json.owners[0].objectId = "U3"; + json.owners[0].objectId = 'U3'; expect(matchesQuery(json, q)).toBe(false); const u3 = new ParseUser(); - u3.id = "U3"; - img = new ParseObject("Image"); - img.set("owners", [u3]); + u3.id = 'U3'; + img = new ParseObject('Image'); + img.set('owners', [u3]); expect(matchesQuery(q.className, img, [], q)).toBe(false); }); - it("matches on inequalities", () => { - const player = new ParseObject("Person"); - player - .set("score", 12) - .set("name", "Bill") - .set("birthday", new Date(1980, 2, 4)); + it('matches on inequalities', () => { + const player = new ParseObject('Person'); + player.set('score', 12).set('name', 'Bill').set('birthday', new Date(1980, 2, 4)); - let q = new ParseQuery("Person"); - q.lessThan("score", 15); + let q = new ParseQuery('Person'); + q.lessThan('score', 15); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThan("score", 10); + q.lessThan('score', 10); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery("Person"); - q.lessThanOrEqualTo("score", 15); + q = new ParseQuery('Person'); + q.lessThanOrEqualTo('score', 15); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThanOrEqualTo("score", 12); + q.lessThanOrEqualTo('score', 12); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.lessThanOrEqualTo("score", 10); + q.lessThanOrEqualTo('score', 10); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery("Person"); - q.greaterThan("score", 15); + q = new ParseQuery('Person'); + q.greaterThan('score', 15); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.greaterThan("score", 10); + q.greaterThan('score', 10); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery("Person"); - q.greaterThanOrEqualTo("score", 15); + q = new ParseQuery('Person'); + q.greaterThanOrEqualTo('score', 15); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.greaterThanOrEqualTo("score", 12); + q.greaterThanOrEqualTo('score', 12); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.greaterThanOrEqualTo("score", 10); + q.greaterThanOrEqualTo('score', 10); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery("Person"); - q.notEqualTo("score", 12); + q = new ParseQuery('Person'); + q.notEqualTo('score', 12); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q.notEqualTo("score", 40); + q.notEqualTo('score', 40); expect(matchesQuery(q.className, player, [], q)).toBe(true); }); - it("matches an $or query", () => { - const player = new ParseObject("Player"); - player.set("score", 12).set("name", "Player 1"); + it('matches an $or query', () => { + const player = new ParseObject('Player'); + 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("name", "Player 2"); - const q3 = new ParseQuery("Player"); - q3.equalTo("name", "Player 3"); + const q = new ParseQuery('Player'); + q.equalTo('name', 'Player 1'); + const q2 = new ParseQuery('Player'); + q2.equalTo('name', 'Player 2'); + const q3 = new ParseQuery('Player'); + q3.equalTo('name', 'Player 3'); const orQuery1 = ParseQuery.or(q, q2); const orQuery2 = ParseQuery.or(q2, q3); expect(matchesQuery(q.className, player, [], q)).toBe(true); @@ -271,16 +260,16 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, player, [], orQuery2)).toBe(false); }); - it("matches an $and query", () => { - const player = new ParseObject("Player"); - player.set("score", 12).set("name", "Player 1"); + it('matches an $and query', () => { + const player = new ParseObject('Player'); + 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); - const q3 = new ParseQuery("Player"); - q3.equalTo("score", 100); + const q = new ParseQuery('Player'); + q.equalTo('name', 'Player 1'); + const q2 = new ParseQuery('Player'); + q2.equalTo('score', 12); + const q3 = new ParseQuery('Player'); + q3.equalTo('score', 100); const andQuery1 = ParseQuery.and(q, q2); const andQuery2 = ParseQuery.and(q, q3); expect(matchesQuery(q.className, player, [], q)).toBe(true); @@ -289,16 +278,16 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, player, [], andQuery2)).toBe(false); }); - it("matches an $nor query", () => { - const player = new ParseObject("Player"); - player.set("score", 12).set("name", "Player 1"); + it('matches an $nor query', () => { + const player = new ParseObject('Player'); + 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("name", "Player 2"); - const q3 = new ParseQuery("Player"); - q3.equalTo("name", "Player 3"); + const q = new ParseQuery('Player'); + q.equalTo('name', 'Player 1'); + const q2 = new ParseQuery('Player'); + q2.equalTo('name', 'Player 2'); + const q3 = new ParseQuery('Player'); + q3.equalTo('name', 'Player 3'); const norQuery1 = ParseQuery.nor(q, q2); const norQuery2 = ParseQuery.nor(q2, q3); @@ -309,53 +298,53 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, player, [], norQuery2)).toBe(true); }); - it("matches $regex queries", () => { - const player = new ParseObject("Player"); - player.set("score", 12).set("name", "Player 1"); + it('matches $regex queries', () => { + const player = new ParseObject('Player'); + player.set('score', 12).set('name', 'Player 1'); - let q = new ParseQuery("Player"); - q.startsWith("name", "Play"); + let q = new ParseQuery('Player'); + q.startsWith('name', 'Play'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.startsWith("name", "Ploy"); + q.startsWith('name', 'Ploy'); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery("Player"); - q.endsWith("name", " 1"); + q = new ParseQuery('Player'); + q.endsWith('name', ' 1'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.endsWith("name", " 2"); + q.endsWith('name', ' 2'); expect(matchesQuery(q.className, player, [], q)).toBe(false); // Check that special characters are escaped - player.set("name", "Android-7"); - q = new ParseQuery("Player"); - q.contains("name", "d-7"); + player.set('name', 'Android-7'); + q = new ParseQuery('Player'); + q.contains('name', 'd-7'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q = new ParseQuery("Player"); - q.matches("name", /A.d/, "m"); + q = new ParseQuery('Player'); + q.matches('name', /A.d/, 'm'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.matches("name", /A[^n]d/); + q.matches('name', /A[^n]d/); expect(matchesQuery(q.className, player, [], q)).toBe(false); // Check that the string \\E is returned to normal - player.set("name", "Slash \\E"); - q = new ParseQuery("Player"); - q.endsWith("name", "h \\E"); + player.set('name', 'Slash \\E'); + q = new ParseQuery('Player'); + q.endsWith('name', 'h \\E'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.endsWith("name", "h \\Ee"); + q.endsWith('name', 'h \\Ee'); expect(matchesQuery(q.className, player, [], q)).toBe(false); - player.set("name", "Slash \\Q and more"); - q = new ParseQuery("Player"); - q.contains("name", "h \\Q and"); + player.set('name', 'Slash \\Q and more'); + q = new ParseQuery('Player'); + q.contains('name', 'h \\Q and'); expect(matchesQuery(q.className, player, [], q)).toBe(true); - q.contains("name", "h \\Q or"); + q.contains('name', 'h \\Q or'); expect(matchesQuery(q.className, player, [], q)).toBe(false); - q = new ParseQuery("Player"); - q._addCondition("status", "$regex", { + q = new ParseQuery('Player'); + q._addCondition('status', '$regex', { test: function () { return true; }, @@ -363,55 +352,55 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, player, [], q)).toBe(true); }); - it("matches $nearSphere queries", () => { - let q = new ParseQuery("Checkin"); - q.near("location", new ParseGeoPoint(20, 20)); + it('matches $nearSphere queries', () => { + let q = new ParseQuery('Checkin'); + q.near('location', new ParseGeoPoint(20, 20)); // With no max distance, any GeoPoint is 'near' - const pt = new ParseObject("Checkin"); - pt.set("location", new ParseGeoPoint(40, 40)); + const pt = new ParseObject('Checkin'); + pt.set('location', new ParseGeoPoint(40, 40)); - const ptUndefined = new ParseObject("Checkin"); + const ptUndefined = new ParseObject('Checkin'); - const ptNull = new ParseObject("Checkin"); - ptNull.set("location", null); + const ptNull = new ParseObject('Checkin'); + ptNull.set('location', null); expect(matchesQuery(q.className, pt, [], q)).toBe(true); expect(matchesQuery(q.className, ptUndefined, [], q)).toBe(false); expect(matchesQuery(q.className, ptNull, [], q)).toBe(false); - q = new ParseQuery("Checkin"); - pt.set("location", new ParseGeoPoint(40, 40)); + q = new ParseQuery('Checkin'); + pt.set('location', new ParseGeoPoint(40, 40)); - q.withinRadians("location", new ParseGeoPoint(30, 30), 0.3); + q.withinRadians('location', new ParseGeoPoint(30, 30), 0.3); expect(matchesQuery(q.className, pt, [], q)).toBe(true); - q.withinRadians("location", new ParseGeoPoint(30, 30), 0.2); + q.withinRadians('location', new ParseGeoPoint(30, 30), 0.2); expect(matchesQuery(q.className, pt, [], q)).toBe(false); - q = new ParseQuery("Checkin"); - q._addCondition("location", "$maxDistance", 100); + q = new ParseQuery('Checkin'); + q._addCondition('location', '$maxDistance', 100); expect(matchesQuery(q.className, pt, [], q)).toBe(true); }); - it("matches $within queries", () => { - const caltrainStation = new ParseObject("Checkin"); + it('matches $within queries', () => { + const caltrainStation = new ParseObject('Checkin'); caltrainStation - .set("name", "Caltrain") - .set("location", new ParseGeoPoint(37.776346, -122.394218)); + .set('name', 'Caltrain') + .set('location', new ParseGeoPoint(37.776346, -122.394218)); - const santaClara = new ParseObject("Checkin"); + const santaClara = new ParseObject('Checkin'); santaClara - .set("name", "Santa Clara") - .set("location", new ParseGeoPoint(37.325635, -121.945753)); + .set('name', 'Santa Clara') + .set('location', new ParseGeoPoint(37.325635, -121.945753)); - const noLocation = new ParseObject("Checkin"); - noLocation.set("name", "Santa Clara"); + const noLocation = new ParseObject('Checkin'); + noLocation.set('name', 'Santa Clara'); - const nullLocation = new ParseObject("Checkin"); - nullLocation.set("name", "Santa Clara").set("location", null); + const nullLocation = new ParseObject('Checkin'); + nullLocation.set('name', 'Santa Clara').set('location', null); - let q = new ParseQuery("Checkin").withinGeoBox( - "location", + let q = new ParseQuery('Checkin').withinGeoBox( + 'location', new ParseGeoPoint(37.708813, -122.526398), new ParseGeoPoint(37.822802, -122.373962) ); @@ -421,8 +410,8 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, noLocation, [], q)).toBe(false); expect(matchesQuery(q.className, nullLocation, [], q)).toBe(false); // Invalid rectangles - q = new ParseQuery("Checkin").withinGeoBox( - "location", + q = new ParseQuery('Checkin').withinGeoBox( + 'location', new ParseGeoPoint(37.822802, -122.373962), new ParseGeoPoint(37.708813, -122.526398) ); @@ -430,8 +419,8 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, caltrainStation, [], q)).toBe(false); expect(matchesQuery(q.className, santaClara, [], q)).toBe(false); - q = new ParseQuery("Checkin").withinGeoBox( - "location", + q = new ParseQuery('Checkin').withinGeoBox( + 'location', new ParseGeoPoint(37.708813, -122.373962), new ParseGeoPoint(37.822802, -122.526398) ); @@ -440,187 +429,175 @@ describe("OfflineQuery", () => { expect(matchesQuery(q.className, santaClara, [], q)).toBe(false); }); - it("matches on subobjects with dot notation", () => { - const message = new ParseObject("Message"); - message.set("test", "content").set("status", { x: "read", y: "delivered" }); + it('matches on subobjects with dot notation', () => { + const message = new ParseObject('Message'); + message.set('test', 'content').set('status', { x: 'read', y: 'delivered' }); - let q = new ParseQuery("Message"); - q.equalTo("status.x", "read"); + let q = new ParseQuery('Message'); + q.equalTo('status.x', 'read'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.equalTo("status.z", "read"); + q = new ParseQuery('Message'); + q.equalTo('status.z', 'read'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.equalTo("status.x", "delivered"); + q = new ParseQuery('Message'); + q.equalTo('status.x', 'delivered'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.notEqualTo("status.x", "read"); + q = new ParseQuery('Message'); + q.notEqualTo('status.x', 'read'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.notEqualTo("status.z", "read"); + q = new ParseQuery('Message'); + q.notEqualTo('status.z', 'read'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.notEqualTo("status.x", "delivered"); + q = new ParseQuery('Message'); + q.notEqualTo('status.x', 'delivered'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.exists("status.x"); + q = new ParseQuery('Message'); + q.exists('status.x'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.exists("status.z"); + q = new ParseQuery('Message'); + q.exists('status.z'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.exists("nonexistent.x"); + q = new ParseQuery('Message'); + q.exists('nonexistent.x'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.doesNotExist("status.x"); + q = new ParseQuery('Message'); + q.doesNotExist('status.x'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q.doesNotExist("status.z"); + q = new ParseQuery('Message'); + q.doesNotExist('status.z'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.doesNotExist("nonexistent.z"); + q = new ParseQuery('Message'); + q.doesNotExist('nonexistent.z'); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.equalTo("status.x", "read"); - q.doesNotExist("status.y"); + q = new ParseQuery('Message'); + q.equalTo('status.x', 'read'); + q.doesNotExist('status.y'); expect(matchesQuery(q.className, message, [], q)).toBe(false); - q = new ParseQuery("Message"); - q._addCondition("status", "$exists", "invalid"); + q = new ParseQuery('Message'); + q._addCondition('status', '$exists', 'invalid'); expect(matchesQuery(q.className, message, [], q)).toBe(true); }); - it("should support containedIn with pointers", () => { - const profile = new ParseObject("Profile"); - profile.id = "abc"; - const message = new ParseObject("Message"); - message.set("profile", profile); + it('should support containedIn with pointers', () => { + const profile = new ParseObject('Profile'); + profile.id = 'abc'; + const message = new ParseObject('Message'); + message.set('profile', profile); - let q = new ParseQuery("Message"); - q.containedIn("profile", [ - ParseObject.fromJSON({ className: "Profile", objectId: "abc" }), - ParseObject.fromJSON({ className: "Profile", objectId: "def" }), + let q = new ParseQuery('Message'); + 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 = new ParseQuery('Message'); + q.containedIn('profile', [ + ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), + ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it("should support notContainedIn with pointers", () => { - const profile = new ParseObject("Profile"); - profile.id = "abc"; - let message = new ParseObject("Message"); - message.id = "O1"; - message.set("profile", profile); - - let q = new ParseQuery("Message"); - q.notContainedIn("profile", [ - ParseObject.fromJSON({ className: "Profile", objectId: "def" }), - ParseObject.fromJSON({ className: "Profile", objectId: "ghi" }), + it('should support notContainedIn with pointers', () => { + const profile = new ParseObject('Profile'); + profile.id = 'abc'; + let message = new ParseObject('Message'); + message.id = 'O1'; + message.set('profile', profile); + + let q = new ParseQuery('Message'); + 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" }), + 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' }), ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it("should support containedIn queries with [objectId]", () => { - const profile = new ParseObject("Profile"); - profile.id = "abc"; - let message = new ParseObject("Message"); - message.set("profile", profile); + it('should support containedIn queries with [objectId]', () => { + const profile = new ParseObject('Profile'); + profile.id = 'abc'; + let message = new ParseObject('Message'); + message.set('profile', profile); - let q = new ParseQuery("Message"); - q.containedIn("profile", ["abc", "def"]); + let q = new ParseQuery('Message'); + q.containedIn('profile', ['abc', 'def']); expect(matchesQuery(q.className, message, [], q)).toBe(true); - profile.id = "ghi"; - message = new ParseObject("Message"); - message.set("profile", profile); + profile.id = 'ghi'; + message = new ParseObject('Message'); + message.set('profile', profile); - q = new ParseQuery("Message"); - q.containedIn("profile", ["abc", "def"]); + q = new ParseQuery('Message'); + q.containedIn('profile', ['abc', 'def']); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it("should support notContainedIn queries with [objectId]", () => { - const profile = new ParseObject("Profile"); - profile.id = "ghi"; - const message = new ParseObject("Message"); - message.set("profile", profile); + it('should support notContainedIn queries with [objectId]', () => { + const profile = new ParseObject('Profile'); + profile.id = 'ghi'; + const message = new ParseObject('Message'); + message.set('profile', profile); - let q = new ParseQuery("Message"); - q.notContainedIn("profile", ["abc", "def"]); + let q = new ParseQuery('Message'); + q.notContainedIn('profile', ['abc', 'def']); expect(matchesQuery(q.className, message, [], q)).toBe(true); - q = new ParseQuery("Message"); - q.notContainedIn("profile", ["abc", "def", "ghi"]); + q = new ParseQuery('Message'); + q.notContainedIn('profile', ['abc', 'def', 'ghi']); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); - it("should support matchesKeyInQuery", () => { - const restaurant = new ParseObject("Restaurant"); - restaurant.set("ratings", 5); - restaurant.set("location", "Earth"); - const person1 = new ParseObject("Person"); - person1.set("hometown", "Earth"); - const person2 = new ParseObject("Person"); - person2.set("hometown", "Mars"); + it('should support matchesKeyInQuery', () => { + const restaurant = new ParseObject('Restaurant'); + restaurant.set('ratings', 5); + restaurant.set('location', 'Earth'); + const person1 = new ParseObject('Person'); + person1.set('hometown', 'Earth'); + const person2 = new ParseObject('Person'); + person2.set('hometown', 'Mars'); - let query = new ParseQuery("Restaurant"); - query.greaterThan("rating", 4); - let mainQuery = new ParseQuery("Person"); + let query = new ParseQuery('Restaurant'); + query.greaterThan('rating', 4); + let mainQuery = new ParseQuery('Person'); - mainQuery.matchesKeyInQuery("hometown", "location", query); + mainQuery.matchesKeyInQuery('hometown', 'location', query); expect( - matchesQuery( - mainQuery.className, - person1, - [person1, person2, restaurant], - mainQuery - ) + matchesQuery(mainQuery.className, person1, [person1, person2, restaurant], mainQuery) ).toBe(true); expect( - matchesQuery( - mainQuery.className, - person2, - [person1, person2, restaurant], - mainQuery - ) + matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery) ).toBe(false); - expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe( - false - ); + expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe(false); - query = new ParseQuery("Restaurant"); - query.greaterThan("rating", 4); - mainQuery = new ParseQuery("Person"); + query = new ParseQuery('Restaurant'); + query.greaterThan('rating', 4); + mainQuery = new ParseQuery('Person'); - mainQuery.doesNotMatchKeyInQuery("hometown", "location", query); + mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); expect( matchesQuery( mainQuery.className, @@ -630,103 +607,76 @@ describe("OfflineQuery", () => { ) ).toBe(false); expect( - matchesQuery( - mainQuery.className, - person2, - [person1, person2, restaurant], - mainQuery - ) + matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery) ).toBe(true); - expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe( - false - ); + expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe(false); }); - it("should support matchesQuery", () => { + it('should support matchesQuery', () => { const parentObjects = []; const childObjects = []; for (let i = 0; i < 10; i += 1) { - const child = new ParseObject("ChildObject"); + const child = new ParseObject('ChildObject'); child.id = 100 + i; - child.set("x", i); - const parent = new ParseObject("ParentObject"); + child.set('x', i); + const parent = new ParseObject('ParentObject'); parent.id = 10 + i; - parent.set("child", child); + parent.set('child', child); childObjects.push(child); parentObjects.push(parent); } - let subQuery = new ParseQuery("ChildObject"); - subQuery.greaterThan("x", 5); - let q = new ParseQuery("ParentObject"); - q.matchesQuery("child", subQuery); + let subQuery = new ParseQuery('ChildObject'); + subQuery.greaterThan('x', 5); + let q = new ParseQuery('ParentObject'); + q.matchesQuery('child', subQuery); expect( - matchesQuery( - q.className, - parentObjects[0], - [...parentObjects, ...childObjects], - q - ) + matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q) ).toBe(false); expect( - matchesQuery( - q.className, - parentObjects[9], - [...parentObjects, ...childObjects], - q - ) + 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); + 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 - ) + matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q) ).toBe(true); expect( - matchesQuery( - q.className, - parentObjects[9], - [...parentObjects, ...childObjects], - q - ) + matchesQuery(q.className, parentObjects[9], [...parentObjects, ...childObjects], q) ).toBe(false); expect(matchesQuery(q.className, parentObjects[0], [], q)).toBe(true); }); - it("should support containedBy query", () => { - const obj1 = new ParseObject("Numbers"); - const obj2 = new ParseObject("Numbers"); - const obj3 = new ParseObject("Numbers"); - obj1.set("numbers", [0, 1, 2]); - obj2.set("numbers", [2, 0]); - obj3.set("numbers", [1, 2, 3, 4]); + it('should support containedBy query', () => { + const obj1 = new ParseObject('Numbers'); + const obj2 = new ParseObject('Numbers'); + const obj3 = new ParseObject('Numbers'); + obj1.set('numbers', [0, 1, 2]); + obj2.set('numbers', [2, 0]); + obj3.set('numbers', [1, 2, 3, 4]); - const q = new ParseQuery("Numbers"); - q.containedBy("numbers", [1, 2, 3, 4, 5]); + const q = new ParseQuery('Numbers'); + q.containedBy('numbers', [1, 2, 3, 4, 5]); expect(matchesQuery(q.className, obj1, [], q)).toBe(false); expect(matchesQuery(q.className, obj2, [], q)).toBe(false); expect(matchesQuery(q.className, obj3, [], q)).toBe(true); }); - it("should support withinPolygon query", () => { - const sacramento = new ParseObject("Location"); - sacramento.set("location", new ParseGeoPoint(38.52, -121.5)); - sacramento.set("name", "Sacramento"); + it('should support withinPolygon query', () => { + const sacramento = new ParseObject('Location'); + sacramento.set('location', new ParseGeoPoint(38.52, -121.5)); + sacramento.set('name', 'Sacramento'); - const honolulu = new ParseObject("Location"); - honolulu.set("location", new ParseGeoPoint(21.35, -157.93)); - honolulu.set("name", "Honolulu"); + const honolulu = new ParseObject('Location'); + honolulu.set('location', new ParseGeoPoint(21.35, -157.93)); + honolulu.set('name', 'Honolulu'); - const sf = new ParseObject("Location"); - sf.set("location", new ParseGeoPoint(37.75, -122.68)); - sf.set("name", "San Francisco"); + const sf = new ParseObject('Location'); + sf.set('location', new ParseGeoPoint(37.75, -122.68)); + sf.set('name', 'San Francisco'); const points = [ new ParseGeoPoint(37.85, -122.33), @@ -734,15 +684,15 @@ describe("OfflineQuery", () => { new ParseGeoPoint(37.68, -122.9), new ParseGeoPoint(37.68, -122.33), ]; - const q = new ParseQuery("Location"); - q.withinPolygon("location", points); + const q = new ParseQuery('Location'); + q.withinPolygon('location', points); expect(matchesQuery(q.className, sacramento, [], q)).toBe(false); expect(matchesQuery(q.className, honolulu, [], q)).toBe(false); expect(matchesQuery(q.className, sf, [], q)).toBe(true); }); - it("should support polygonContains query", () => { + it('should support polygonContains query', () => { const p1 = [ [0, 0], [0, 1], @@ -766,30 +716,30 @@ describe("OfflineQuery", () => { const polygon1 = new ParsePolygon(p1); const polygon2 = new ParsePolygon(p2); const polygon3 = new ParsePolygon(p3); - const obj1 = new ParseObject("Bounds"); - const obj2 = new ParseObject("Bounds"); - const obj3 = new ParseObject("Bounds"); - obj1.set("polygon", polygon1); - obj2.set("polygon", polygon2); - obj3.set("polygon", polygon3); + const obj1 = new ParseObject('Bounds'); + const obj2 = new ParseObject('Bounds'); + const obj3 = new ParseObject('Bounds'); + obj1.set('polygon', polygon1); + obj2.set('polygon', polygon2); + obj3.set('polygon', polygon3); const point = new ParseGeoPoint(0.5, 0.5); - const q = new ParseQuery("Bounds"); - q.polygonContains("polygon", point); + const q = new ParseQuery('Bounds'); + q.polygonContains('polygon', point); expect(matchesQuery(q.className, obj1, [], q)).toBe(true); expect(matchesQuery(q.className, obj2, [], q)).toBe(true); expect(matchesQuery(q.className, obj3, [], q)).toBe(false); }); - it("should validate query", () => { - let query = new ParseQuery("TestObject"); - query.equalTo("foo", "bar"); + it('should validate query', () => { + let query = new ParseQuery('TestObject'); + query.equalTo('foo', 'bar'); try { validateQuery(query); validateQuery(query.toJSON()); - query.matches("myString", "football", "m"); + query.matches('myString', 'football', 'm'); validateQuery(query); expect(true).toBe(true); @@ -798,8 +748,8 @@ describe("OfflineQuery", () => { expect(false).toEqual(true); } - query = new ParseQuery("TestObject"); - query.matches("myString", "football", "some invalid thing"); + query = new ParseQuery('TestObject'); + query.matches('myString', 'football', 'some invalid thing'); try { validateQuery(query); expect(true).toBe(false); @@ -807,8 +757,8 @@ describe("OfflineQuery", () => { expect(e.code).toEqual(ParseError.INVALID_QUERY); } - query = new ParseQuery("TestObject"); - query.equalTo("$foo", "bar"); + query = new ParseQuery('TestObject'); + query.equalTo('$foo', 'bar'); try { validateQuery(query); expect(true).toBe(false); diff --git a/src/__tests__/Parse-test.js b/src/__tests__/Parse-test.js index ecddb9498..d78d53acd 100644 --- a/src/__tests__/Parse-test.js +++ b/src/__tests__/Parse-test.js @@ -7,77 +7,77 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../CryptoController"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../Parse"); -jest.dontMock("../LocalDatastore"); -jest.dontMock("crypto-js/aes"); - -const CoreManager = require("../CoreManager"); -const Parse = require("../Parse"); - -describe("Parse module", () => { - it("can be initialized with keys", () => { - Parse.initialize("A", "B"); - expect(CoreManager.get("APPLICATION_ID")).toBe("A"); - expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("B"); - - Parse._initialize("A", "B", "C"); - expect(CoreManager.get("APPLICATION_ID")).toBe("A"); - expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("B"); - expect(CoreManager.get("MASTER_KEY")).toBe("C"); - }); - - it("enables master key use in the node build", () => { - expect(typeof Parse.Cloud.useMasterKey).toBe("function"); +jest.dontMock('../CoreManager'); +jest.dontMock('../CryptoController'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../Parse'); +jest.dontMock('../LocalDatastore'); +jest.dontMock('crypto-js/aes'); + +const CoreManager = require('../CoreManager'); +const Parse = require('../Parse'); + +describe('Parse module', () => { + it('can be initialized with keys', () => { + Parse.initialize('A', 'B'); + expect(CoreManager.get('APPLICATION_ID')).toBe('A'); + expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('B'); + + Parse._initialize('A', 'B', 'C'); + expect(CoreManager.get('APPLICATION_ID')).toBe('A'); + expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('B'); + expect(CoreManager.get('MASTER_KEY')).toBe('C'); + }); + + it('enables master key use in the node build', () => { + expect(typeof Parse.Cloud.useMasterKey).toBe('function'); Parse.Cloud.useMasterKey(); - expect(CoreManager.get("USE_MASTER_KEY")).toBe(true); + expect(CoreManager.get('USE_MASTER_KEY')).toBe(true); }); - it("exposes certain keys as properties", () => { - Parse.applicationId = "123"; - expect(CoreManager.get("APPLICATION_ID")).toBe("123"); - expect(Parse.applicationId).toBe("123"); + it('exposes certain keys as properties', () => { + Parse.applicationId = '123'; + expect(CoreManager.get('APPLICATION_ID')).toBe('123'); + expect(Parse.applicationId).toBe('123'); - Parse.javaScriptKey = "456"; - expect(CoreManager.get("JAVASCRIPT_KEY")).toBe("456"); - expect(Parse.javaScriptKey).toBe("456"); + Parse.javaScriptKey = '456'; + expect(CoreManager.get('JAVASCRIPT_KEY')).toBe('456'); + expect(Parse.javaScriptKey).toBe('456'); - Parse.masterKey = "789"; - expect(CoreManager.get("MASTER_KEY")).toBe("789"); - expect(Parse.masterKey).toBe("789"); + Parse.masterKey = '789'; + expect(CoreManager.get('MASTER_KEY')).toBe('789'); + expect(Parse.masterKey).toBe('789'); - Parse.serverURL = "http://example.com"; - expect(CoreManager.get("SERVER_URL")).toBe("http://example.com"); - expect(Parse.serverURL).toBe("http://example.com"); + Parse.serverURL = 'http://example.com'; + expect(CoreManager.get('SERVER_URL')).toBe('http://example.com'); + expect(Parse.serverURL).toBe('http://example.com'); - Parse.liveQueryServerURL = "https://example.com"; - expect(CoreManager.get("LIVEQUERY_SERVER_URL")).toBe("https://example.com"); - expect(Parse.liveQueryServerURL).toBe("https://example.com"); + Parse.liveQueryServerURL = 'https://example.com'; + expect(CoreManager.get('LIVEQUERY_SERVER_URL')).toBe('https://example.com'); + expect(Parse.liveQueryServerURL).toBe('https://example.com'); }); - it("can set auth type and token", () => { - Parse.serverAuthType = "bearer"; - expect(CoreManager.get("SERVER_AUTH_TYPE")).toBe("bearer"); - expect(Parse.serverAuthType).toBe("bearer"); + it('can set auth type and token', () => { + Parse.serverAuthType = 'bearer'; + expect(CoreManager.get('SERVER_AUTH_TYPE')).toBe('bearer'); + expect(Parse.serverAuthType).toBe('bearer'); - Parse.serverAuthToken = "some_token"; - expect(CoreManager.get("SERVER_AUTH_TOKEN")).toBe("some_token"); - expect(Parse.serverAuthToken).toBe("some_token"); + Parse.serverAuthToken = 'some_token'; + expect(CoreManager.get('SERVER_AUTH_TOKEN')).toBe('some_token'); + expect(Parse.serverAuthToken).toBe('some_token'); }); - it("can set idempotency", () => { + it('can set idempotency', () => { expect(Parse.idempotency).toBe(false); Parse.idempotency = true; - expect(CoreManager.get("IDEMPOTENCY")).toBe(true); + expect(CoreManager.get('IDEMPOTENCY')).toBe(true); expect(Parse.idempotency).toBe(true); Parse.idempotency = false; expect(Parse.idempotency).toBe(false); }); - it("can set LocalDatastoreController", () => { + it('can set LocalDatastoreController', () => { const controller = { fromPinWithName: function () {}, pinWithName: function () {}, @@ -89,7 +89,7 @@ describe("Parse module", () => { expect(CoreManager.getLocalDatastoreController()).toBe(controller); }); - it("can set AsyncStorage", () => { + it('can set AsyncStorage', () => { const controller = { getItem: function () {}, setItem: function () {}, @@ -104,15 +104,15 @@ describe("Parse module", () => { expect(CoreManager.getAsyncStorage()).toBe(controller); }); - it("can enable LocalDatastore", () => { - jest.spyOn(console, "log").mockImplementationOnce(() => {}); + it('can enable LocalDatastore', () => { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); Parse.LocalDatastore.isEnabled = false; Parse.enableLocalDatastore(); expect(Parse.LocalDatastore.isEnabled).toBe(true); expect(Parse.isLocalDatastoreEnabled()).toBe(true); }); - it("can dump LocalDatastore", async () => { + it('can dump LocalDatastore', async () => { Parse.LocalDatastore.isEnabled = false; let LDS = await Parse.dumpLocalDatastore(); expect(LDS).toEqual({}); @@ -122,74 +122,74 @@ describe("Parse module", () => { pinWithName: function () {}, unPinWithName: function () {}, getAllContents: function () { - return Promise.resolve({ key: "value" }); + return Promise.resolve({ key: 'value' }); }, clear: function () {}, }; Parse.setLocalDatastoreController(controller); LDS = await Parse.dumpLocalDatastore(); - expect(LDS).toEqual({ key: "value" }); + expect(LDS).toEqual({ key: 'value' }); }); - it("can enable encrypter CurrentUser", () => { - jest.spyOn(console, "log").mockImplementationOnce(() => {}); - process.env.PARSE_BUILD = "browser"; + it('can enable encrypter CurrentUser', () => { + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + process.env.PARSE_BUILD = 'browser'; Parse.encryptedUser = false; Parse.enableEncryptedUser(); expect(Parse.encryptedUser).toBe(true); expect(Parse.isEncryptedUserEnabled()).toBe(true); }); - it("can set an encrypt token as String", () => { - Parse.secret = "My Super secret key"; - expect(CoreManager.get("ENCRYPTED_KEY")).toBe("My Super secret key"); - expect(Parse.secret).toBe("My Super secret key"); + it('can set an encrypt token as String', () => { + Parse.secret = 'My Super secret key'; + expect(CoreManager.get('ENCRYPTED_KEY')).toBe('My Super secret key'); + expect(Parse.secret).toBe('My Super secret key'); }); - it("can set and get request batch size", () => { - expect(CoreManager.get("REQUEST_BATCH_SIZE")).toBe(20); - CoreManager.set("REQUEST_BATCH_SIZE", 4); - expect(CoreManager.get("REQUEST_BATCH_SIZE")).toBe(4); - CoreManager.set("REQUEST_BATCH_SIZE", 20); + it('can set and get request batch size', () => { + expect(CoreManager.get('REQUEST_BATCH_SIZE')).toBe(20); + CoreManager.set('REQUEST_BATCH_SIZE', 4); + expect(CoreManager.get('REQUEST_BATCH_SIZE')).toBe(4); + CoreManager.set('REQUEST_BATCH_SIZE', 20); }); - it("_request", () => { + it('_request', () => { const controller = { request: jest.fn(), ajax: jest.fn(), }; CoreManager.setRESTController(controller); - Parse._request("POST", "classes/TestObject"); + Parse._request('POST', 'classes/TestObject'); const [method, path] = controller.request.mock.calls[0]; - expect(method).toBe("POST"); - expect(path).toBe("classes/TestObject"); + expect(method).toBe('POST'); + expect(path).toBe('classes/TestObject'); }); - it("_ajax", () => { + it('_ajax', () => { const controller = { request: jest.fn(), ajax: jest.fn(), }; CoreManager.setRESTController(controller); - Parse._ajax("POST", "classes/TestObject"); + Parse._ajax('POST', 'classes/TestObject'); const [method, path] = controller.ajax.mock.calls[0]; - expect(method).toBe("POST"); - expect(path).toBe("classes/TestObject"); + expect(method).toBe('POST'); + expect(path).toBe('classes/TestObject'); }); - it("_getInstallationId", () => { + it('_getInstallationId', () => { const controller = { - currentInstallationId: () => "1234", + currentInstallationId: () => '1234', }; CoreManager.setInstallationController(controller); - expect(Parse._getInstallationId()).toBe("1234"); + expect(Parse._getInstallationId()).toBe('1234'); }); - it("_decode", () => { + it('_decode', () => { expect(Parse._decode(null, 12)).toBe(12); }); - it("_encode", () => { + it('_encode', () => { expect(Parse._encode(12)).toBe(12); }); }); diff --git a/src/__tests__/ParseACL-test.js b/src/__tests__/ParseACL-test.js index 5046316e6..e7ce0d101 100644 --- a/src/__tests__/ParseACL-test.js +++ b/src/__tests__/ParseACL-test.js @@ -7,7 +7,7 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../ParseACL"); +jest.dontMock('../ParseACL'); const mockRole = function (name) { this.name = name; @@ -15,26 +15,26 @@ const mockRole = function (name) { mockRole.prototype.getName = function () { return this.name; }; -jest.setMock("../ParseRole", mockRole); +jest.setMock('../ParseRole', mockRole); -const ParseACL = require("../ParseACL").default; -const ParseUser = require("../ParseUser").default; -const ParseRole = require("../ParseRole"); +const ParseACL = require('../ParseACL').default; +const ParseUser = require('../ParseUser').default; +const ParseRole = require('../ParseRole'); -describe("ParseACL", () => { - it("can be constructed with no arguments", () => { +describe('ParseACL', () => { + it('can be constructed with no arguments', () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); }); - it("can be constructed with a ParseUser", () => { + it('can be constructed with a ParseUser', () => { const u = new ParseUser(); - u.id = "uid"; + u.id = 'uid'; const a = new ParseACL(u); expect(a.permissionsById).toEqual({ uid: { read: true, write: true } }); }); - it("can be constructed with a map of user IDs", () => { + it('can be constructed with a map of user IDs', () => { const a = new ParseACL({ aUserId: { read: true, write: false } }); expect(a.permissionsById).toEqual({ aUserId: { @@ -44,68 +44,56 @@ describe("ParseACL", () => { }); }); - it("throws when constructed with an invalid permissions map", () => { + it('throws when constructed with an invalid permissions map', () => { let err = function () { new ParseACL({ aUserId: { foo: true, bar: false } }); }; - expect(err).toThrow( - "Tried to create an ACL with an invalid permission type." - ); + 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", () => { + it('throws a helpful error when constructed with a function', () => { expect(function () { new ParseACL(function () {}); - }).toThrow("ParseACL constructed with a function. Did you forget ()?"); + }).toThrow('ParseACL constructed with a function. Did you forget ()?'); }); - it("throws when setting an invalid user id", () => { + 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); - }).toThrow("Cannot get access for a ParseUser without an ID"); + }).toThrow('Cannot get access for a ParseUser without an ID'); }); - it("throws when setting an invalid access", () => { + 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", () => { + it('throws when role does not have name', () => { const a = new ParseACL(); expect(() => { a.setReadAccess(new ParseRole(), true); - }).toThrow("Role must have a name"); + }).toThrow('Role must have a name'); expect(() => { a.getReadAccess(new ParseRole(), true); - }).toThrow("Role must have a name"); + }).toThrow('Role must have a name'); }); - it("throws when setting an invalid role", () => { + 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", () => { + it('can be rendered to JSON format', () => { const a = new ParseACL({ aUserId: { read: true, write: false } }); expect(a.toJSON()).toEqual({ aUserId: { @@ -115,26 +103,26 @@ describe("ParseACL", () => { }); }); - it("can set read access for a user", () => { + it('can set read access for a user', () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); // removing a permission that doesn't exist does nothing - a.setReadAccess("aUserId", false); + a.setReadAccess('aUserId', false); expect(a.permissionsById).toEqual({}); - a.setReadAccess("aUserId", true); + a.setReadAccess('aUserId', true); expect(a.permissionsById).toEqual({ aUserId: { read: true, }, }); - a.setReadAccess("aUserId", false); + a.setReadAccess('aUserId', false); expect(a.permissionsById).toEqual({}); }); - it("can get read access for a user", () => { + it('can get read access for a user', () => { const a = new ParseACL({ aUserId: { read: true, @@ -142,31 +130,31 @@ describe("ParseACL", () => { }, }); - expect(a.getReadAccess("aUserId")).toBe(true); + expect(a.getReadAccess('aUserId')).toBe(true); }); - it("can set write access for a user", () => { + it('can set write access for a user', () => { const a = new ParseACL(); const u = new ParseUser(); - u.id = "aUserId"; + u.id = 'aUserId'; expect(a.permissionsById).toEqual({}); // removing a permission that doesn't exist does nothing - a.setWriteAccess("aUserId", false); + a.setWriteAccess('aUserId', false); expect(a.permissionsById).toEqual({}); a.setWriteAccess(u, false); expect(a.permissionsById).toEqual({}); - a.setWriteAccess("aUserId", true); + a.setWriteAccess('aUserId', true); expect(a.permissionsById).toEqual({ aUserId: { write: true, }, }); - a.setWriteAccess("aUserId", false); + a.setWriteAccess('aUserId', false); expect(a.permissionsById).toEqual({}); a.setWriteAccess(u, true); @@ -180,7 +168,7 @@ describe("ParseACL", () => { expect(a.permissionsById).toEqual({}); }); - it("can get write access for a user", () => { + it('can get write access for a user', () => { const a = new ParseACL({ aUserId: { read: true, @@ -189,20 +177,20 @@ describe("ParseACL", () => { }); const u = new ParseUser(); - u.id = "aUserId"; + u.id = 'aUserId'; - expect(a.getWriteAccess("aUserId")).toBe(false); + expect(a.getWriteAccess('aUserId')).toBe(false); expect(a.getWriteAccess(u)).toBe(false); }); - it("can set public read access", () => { + it('can set public read access', () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); expect(a.getPublicReadAccess()).toBe(false); a.setPublicReadAccess(true); expect(a.permissionsById).toEqual({ - "*": { + '*': { read: true, }, }); @@ -212,14 +200,14 @@ describe("ParseACL", () => { expect(a.permissionsById).toEqual({}); }); - it("can set public write access", () => { + it('can set public write access', () => { const a = new ParseACL(); expect(a.permissionsById).toEqual({}); expect(a.getPublicWriteAccess()).toBe(false); a.setPublicWriteAccess(true); expect(a.permissionsById).toEqual({ - "*": { + '*': { write: true, }, }); @@ -229,77 +217,73 @@ describe("ParseACL", () => { expect(a.permissionsById).toEqual({}); }); - it("can get role read access", () => { + it('can get role read access', () => { const a = new ParseACL({ - "role:admin": { + 'role:admin': { read: true, write: true, }, }); - expect(a.getRoleReadAccess("admin")).toBe(true); - expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(true); - expect(a.getReadAccess(new ParseRole("admin"))).toBe(true); + expect(a.getRoleReadAccess('admin')).toBe(true); + expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(true); + expect(a.getReadAccess(new ParseRole('admin'))).toBe(true); }); - it("can get role write access", () => { + it('can get role write access', () => { const a = new ParseACL({ - "role:admin": { + 'role:admin': { read: true, write: true, }, }); - expect(a.getRoleWriteAccess("admin")).toBe(true); - expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(true); - expect(a.getWriteAccess(new ParseRole("admin"))).toBe(true); + expect(a.getRoleWriteAccess('admin')).toBe(true); + expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(true); + expect(a.getWriteAccess(new ParseRole('admin'))).toBe(true); }); - it("throws when fetching an invalid role", () => { + 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", () => { + it('can set role read access', () => { const a = new ParseACL(); - expect(a.getRoleReadAccess("admin")).toBe(false); - expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(false); + expect(a.getRoleReadAccess('admin')).toBe(false); + expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(false); - a.setRoleReadAccess("admin", true); - expect(a.getRoleReadAccess("admin")).toBe(true); - expect(a.getRoleWriteAccess("admin")).toBe(false); + a.setRoleReadAccess('admin', true); + expect(a.getRoleReadAccess('admin')).toBe(true); + expect(a.getRoleWriteAccess('admin')).toBe(false); - a.setRoleReadAccess(new ParseRole("admin"), false); - expect(a.getRoleReadAccess(new ParseRole("admin"))).toBe(false); + a.setRoleReadAccess(new ParseRole('admin'), false); + expect(a.getRoleReadAccess(new ParseRole('admin'))).toBe(false); - a.setReadAccess(new ParseRole("admin"), true); - expect(a.getReadAccess(new ParseRole("admin"))).toBe(true); + a.setReadAccess(new ParseRole('admin'), true); + expect(a.getReadAccess(new ParseRole('admin'))).toBe(true); }); - it("can set role write access", () => { + it('can set role write access', () => { const a = new ParseACL(); - expect(a.getRoleWriteAccess("admin")).toBe(false); - expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(false); + expect(a.getRoleWriteAccess('admin')).toBe(false); + expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(false); - a.setRoleWriteAccess("admin", true); - expect(a.getRoleWriteAccess("admin")).toBe(true); - expect(a.getRoleReadAccess("admin")).toBe(false); + a.setRoleWriteAccess('admin', true); + expect(a.getRoleWriteAccess('admin')).toBe(true); + expect(a.getRoleReadAccess('admin')).toBe(false); - a.setRoleWriteAccess(new ParseRole("admin"), false); - expect(a.getRoleWriteAccess(new ParseRole("admin"))).toBe(false); + a.setRoleWriteAccess(new ParseRole('admin'), false); + expect(a.getRoleWriteAccess(new ParseRole('admin'))).toBe(false); - a.setWriteAccess(new ParseRole("admin"), true); - expect(a.getWriteAccess(new ParseRole("admin"))).toBe(true); + a.setWriteAccess(new ParseRole('admin'), true); + expect(a.getWriteAccess(new ParseRole('admin'))).toBe(true); }); - it("can test equality against another ACL", () => { + it('can test equality against another ACL', () => { const a = new ParseACL(); const b = new ParseACL(); @@ -331,32 +315,32 @@ describe("ParseACL", () => { expect(b.equals(a)).toBe(true); expect(a.equals(new ParseACL())).toBe(true); - a.setReadAccess("aUserId", true); - b.setReadAccess("aUserId", true); + a.setReadAccess('aUserId', true); + b.setReadAccess('aUserId', true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); - a.setWriteAccess("aUserId", true); - b.setWriteAccess("aUserId", true); + a.setWriteAccess('aUserId', true); + b.setWriteAccess('aUserId', true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); - a.setWriteAccess("anotherUserId", true); + a.setWriteAccess('anotherUserId', true); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); - b.setWriteAccess("anotherUserId", true); + b.setWriteAccess('anotherUserId', true); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); a.setPublicReadAccess(true); - a.setReadAccess("aUserId", true); - b.setReadAccess("aUserId", true); + a.setReadAccess('aUserId', true); + b.setReadAccess('aUserId', true); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); expect(a.equals({})).toBe(false); - b.setWriteAccess("newUserId", true); + b.setWriteAccess('newUserId', true); expect(a.equals(b)).toBe(false); a.setPublicReadAccess(false); diff --git a/src/__tests__/ParseConfig-test.js b/src/__tests__/ParseConfig-test.js index 69c6fc56d..4e5d96306 100644 --- a/src/__tests__/ParseConfig-test.js +++ b/src/__tests__/ParseConfig-test.js @@ -7,63 +7,63 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../escape"); -jest.dontMock("../ParseConfig"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../RESTController"); -jest.dontMock("../Storage"); -jest.dontMock("../StorageController.default"); -jest.dontMock("./test_helpers/mockAsyncStorage"); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../escape'); +jest.dontMock('../ParseConfig'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../RESTController'); +jest.dontMock('../Storage'); +jest.dontMock('../StorageController.default'); +jest.dontMock('./test_helpers/mockAsyncStorage'); -const mockAsyncStorage = require("./test_helpers/mockAsyncStorage"); -const CoreManager = require("../CoreManager"); -const ParseConfig = require("../ParseConfig").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const Storage = require("../Storage"); +const mockAsyncStorage = require('./test_helpers/mockAsyncStorage'); +const CoreManager = require('../CoreManager'); +const ParseConfig = require('../ParseConfig').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const Storage = require('../Storage'); -CoreManager.set("APPLICATION_ID", "A"); -CoreManager.set("JAVASCRIPT_KEY", "B"); +CoreManager.set('APPLICATION_ID', 'A'); +CoreManager.set('JAVASCRIPT_KEY', 'B'); -describe("ParseConfig", () => { +describe('ParseConfig', () => { beforeEach(() => { ParseConfig._clearCache(); }); - it("exposes attributes via get()", () => { + it('exposes attributes via get()', () => { const c = new ParseConfig(); c.attributes = { - str: "hello", + str: 'hello', num: 44, }; - expect(c.get("str")).toBe("hello"); - expect(c.get("num")).toBe(44); - expect(c.get("nonexistent")).toBe(undefined); + expect(c.get('str')).toBe('hello'); + expect(c.get('num')).toBe(44); + expect(c.get('nonexistent')).toBe(undefined); }); - it("exposes escaped attributes", () => { + it('exposes escaped attributes', () => { const c = new ParseConfig(); c.attributes = { - brackets: "<>", - phone: "AT&T", + brackets: '<>', + phone: 'AT&T', }; - expect(c.escape("brackets")).toBe("<>"); - expect(c.escape("phone")).toBe("AT&T"); - expect(c.escape("phone")).toBe("AT&T"); + expect(c.escape('brackets')).toBe('<>'); + expect(c.escape('phone')).toBe('AT&T'); + expect(c.escape('phone')).toBe('AT&T'); }); - it("can retrieve the current config from disk or cache", () => { - const path = Storage.generatePath("currentConfig"); + 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", + __type: 'GeoPoint', latitude: 20.02, longitude: 30.03, }, @@ -79,26 +79,26 @@ describe("ParseConfig", () => { }); }); - it("can handle decodedData error", async () => { + it('can handle decodedData error', async () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); - const path = Storage.generatePath("currentConfig"); + const path = Storage.generatePath('currentConfig'); await Storage.setItemAsync(path, {}); const config = await ParseConfig.current(); expect(config.attributes).toEqual({}); CoreManager.setStorageController(currentStorage); }); - it("can retrieve the current config from async storage", async () => { + it('can retrieve the current config from async storage', async () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); - const path = Storage.generatePath("currentConfig"); + const path = Storage.generatePath('currentConfig'); await Storage.setItemAsync( path, JSON.stringify({ count: 12, point: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20.02, longitude: 30.03, }, @@ -112,35 +112,35 @@ describe("ParseConfig", () => { 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({ params: { - str: "hello", + str: 'hello', num: 45, file: { - __type: "File", - name: "parse.txt", - url: "https://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'https://files.parsetfss.com/a/parse.txt', }, }, }); }, ajax() {}, }); - ParseConfig.get().then((config) => { - expect(config.get("str")).toBe("hello"); - expect(config.get("num")).toBe(45); - expect(config.get("file").name()).toBe("parse.txt"); - const path = Storage.generatePath("currentConfig"); + ParseConfig.get().then(config => { + expect(config.get('str')).toBe('hello'); + expect(config.get('num')).toBe(45); + expect(config.get('file').name()).toBe('parse.txt'); + const path = Storage.generatePath('currentConfig'); expect(JSON.parse(Storage.getItem(path))).toEqual({ - str: "hello", + str: 'hello', num: 45, file: { - __type: "File", - name: "parse.txt", - url: "https://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'https://files.parsetfss.com/a/parse.txt', }, }); @@ -148,13 +148,13 @@ describe("ParseConfig", () => { }); }); - 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", + str: 'hello2', num: 46, }, result: true, @@ -162,44 +162,44 @@ describe("ParseConfig", () => { }, ajax() {}, }); - 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"); + 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", + str: 'hello2', num: 46, }); done(); }); }); - it("can save a config object that be retrieved with masterkey only", async () => { + it('can save a config object that be retrieved with masterkey only', async () => { CoreManager.setRESTController({ request(method, path, body, options) { - if (method === "PUT") { - expect(method).toBe("PUT"); - expect(path).toBe("config"); + if (method === 'PUT') { + expect(method).toBe('PUT'); + expect(path).toBe('config'); expect(body).toEqual({ - params: { internal: "i", number: 12 }, + params: { internal: 'i', number: 12 }, masterKeyOnly: { internal: true }, }); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - internal: "i", + internal: 'i', number: 12, }, result: true, }); - } else if (method === "GET") { - expect(method).toBe("GET"); - expect(path).toBe("config"); + } else if (method === 'GET') { + expect(method).toBe('GET'); + expect(path).toBe('config'); expect(body).toEqual({}); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - internal: "i", + internal: 'i', number: 12, }, }); @@ -207,24 +207,21 @@ describe("ParseConfig", () => { }, ajax() {}, }); - const config = await ParseConfig.save( - { internal: "i", number: 12 }, - { internal: true } - ); - expect(config.get("internal")).toBe("i"); - expect(config.get("number")).toBe(12); + const config = await ParseConfig.save({ internal: 'i', number: 12 }, { internal: true }); + expect(config.get('internal')).toBe('i'); + expect(config.get('number')).toBe(12); }); - it("can get a config object with master key", async () => { + it('can get a config object with master key', async () => { CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("config"); + expect(method).toBe('GET'); + expect(path).toBe('config'); expect(body).toEqual({}); expect(options).toEqual({ useMasterKey: true }); return Promise.resolve({ params: { - str: "hello", + str: 'hello', num: 45, }, }); @@ -232,57 +229,57 @@ describe("ParseConfig", () => { ajax() {}, }); const config = await ParseConfig.get({ useMasterKey: true }); - expect(config.get("str")).toBe("hello"); - expect(config.get("num")).toBe(45); - const path = Storage.generatePath("currentConfig"); + expect(config.get('str')).toBe('hello'); + expect(config.get('num')).toBe(45); + const path = Storage.generatePath('currentConfig'); expect(JSON.parse(Storage.getItem(path))).toEqual({ - str: "hello", + str: 'hello', num: 45, }); }); - it("rejects save on invalid response", (done) => { + it('rejects save on invalid response', done => { CoreManager.setRESTController({ request() { return Promise.resolve({ result: false }); }, ajax() {}, }); - ParseConfig.save({ str: "hello2", num: 46 }).then( - (config) => { + ParseConfig.save({ str: 'hello2', num: 46 }).then( + config => { expect(config).toBe(1); done(); }, - (error) => { + 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() {}, }); - ParseConfig.get().then(null, (error) => { + ParseConfig.get().then(null, error => { expect(error.code).toBe(107); - expect(error.message).toBe("Config JSON response invalid."); + 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"); + return Promise.reject('failure'); }, ajax() {}, }); - ParseConfig.get().then(null, (error) => { - expect(error).toBe("failure"); + ParseConfig.get().then(null, error => { + expect(error).toBe('failure'); done(); }); }); diff --git a/src/__tests__/ParseError-test.js b/src/__tests__/ParseError-test.js index 893352ba2..3da9dbbef 100644 --- a/src/__tests__/ParseError-test.js +++ b/src/__tests__/ParseError-test.js @@ -7,23 +7,23 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../ParseError"); +jest.dontMock('../ParseError'); -const ParseError = require("../ParseError").default; +const ParseError = require('../ParseError').default; -describe("ParseError", () => { - it("have sensible string representation", () => { - const error = new ParseError(123, "some error message"); +describe('ParseError', () => { + it('have sensible string representation', () => { + const error = new ParseError(123, 'some error message'); - expect(error.toString()).toMatch("ParseError"); - expect(error.toString()).toMatch("123"); - expect(error.toString()).toMatch("some error message"); + expect(error.toString()).toMatch('ParseError'); + expect(error.toString()).toMatch('123'); + expect(error.toString()).toMatch('some error message'); }); - it("has a proper json representation", () => { - const error = new ParseError(123, "some error message"); + it('has a proper json representation', () => { + const error = new ParseError(123, 'some error message'); expect(JSON.parse(JSON.stringify(error))).toEqual({ - message: "some error message", + message: 'some error message', code: 123, }); }); diff --git a/src/__tests__/ParseFile-test.js b/src/__tests__/ParseFile-test.js index 8434d376e..afa210baf 100644 --- a/src/__tests__/ParseFile-test.js +++ b/src/__tests__/ParseFile-test.js @@ -8,31 +8,31 @@ */ /* global File */ jest.autoMockOff(); -jest.mock("http"); -jest.mock("https"); -jest.mock("../ParseACL"); +jest.mock('http'); +jest.mock('https'); +jest.mock('../ParseACL'); -const ParseError = require("../ParseError").default; -const ParseFile = require("../ParseFile").default; -const b64Digit = require("../ParseFile").b64Digit; +const ParseError = require('../ParseError').default; +const ParseFile = require('../ParseFile').default; +const b64Digit = require('../ParseFile').b64Digit; -const ParseObject = require("../ParseObject").default; -const CoreManager = require("../CoreManager"); -const EventEmitter = require("../EventEmitter"); +const ParseObject = require('../ParseObject').default; +const CoreManager = require('../CoreManager'); +const EventEmitter = require('../EventEmitter'); -const mockHttp = require("http"); -const mockHttps = require("https"); +const mockHttp = require('http'); +const mockHttps = require('https'); const mockLocalDatastore = { _updateLocalIdForObject: jest.fn(), _updateObjectIfPinned: jest.fn(), }; -jest.setMock("../LocalDatastore", mockLocalDatastore); +jest.setMock('../LocalDatastore', mockLocalDatastore); function generateSaveMock(prefix) { return function (name, payload, options) { - if (options && typeof options.progress === "function") { - options.progress(0.5, 5, 10, { type: "upload" }); + if (options && typeof options.progress === 'function') { + options.progress(0.5, 5, 10, { type: 'upload' }); } return Promise.resolve({ name: name, @@ -43,176 +43,171 @@ function generateSaveMock(prefix) { const defaultController = CoreManager.getFileController(); -describe("ParseFile", () => { +describe('ParseFile', () => { beforeEach(() => { CoreManager.setFileController({ - saveFile: generateSaveMock("http://files.parsetfss.com/a/"), - saveBase64: generateSaveMock("http://files.parsetfss.com/a/"), + saveFile: generateSaveMock('http://files.parsetfss.com/a/'), + saveBase64: generateSaveMock('http://files.parsetfss.com/a/'), download: () => Promise.resolve({ - base64: "ParseA==", - contentType: "image/png", + base64: 'ParseA==', + contentType: 'image/png', }), }); }); afterEach(() => { - process.env.PARSE_BUILD = "node"; + process.env.PARSE_BUILD = 'node'; }); - it("can create files with base64 encoding", () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe(""); + it('can create files with base64 encoding', () => { + const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe(''); }); - it("can extract data type from base64", () => { - const file = new ParseFile("parse.txt", { - base64: "data:image/png;base64,ParseA==", + it('can extract data type from base64', () => { + const file = new ParseFile('parse.txt', { + base64: 'data:image/png;base64,ParseA==', }); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe("image/png"); + 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", + it('can create files with file uri', () => { + 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"); + 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==", + 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==', }); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe("audio/m4a"); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe('audio/m4a'); }); - 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==", + 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==', }); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe("application/vnd.google-earth.kml+xml"); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe('application/vnd.google-earth.kml+xml'); }); - 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==", + 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==', }); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe("application/vnd.3gpp.pic-bw-var"); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe('application/vnd.3gpp.pic-bw-var'); }); - it("can create files with byte arrays", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe(""); + it('can create files with byte arrays', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe(''); }); - it("can create files with all types of characters", () => { - const file = new ParseFile("parse.txt", [11, 239, 191, 215, 80, 52]); - expect(file._source.base64).toBe("C++/11A0"); - expect(file._source.type).toBe(""); + it('can create files with all types of characters', () => { + const file = new ParseFile('parse.txt', [11, 239, 191, 215, 80, 52]); + expect(file._source.base64).toBe('C++/11A0'); + expect(file._source.type).toBe(''); }); - it("can create an empty file", () => { - const file = new ParseFile("parse.txt"); - expect(file.name()).toBe("parse.txt"); + it('can create an empty file', () => { + const file = new ParseFile('parse.txt'); + expect(file.name()).toBe('parse.txt'); expect(file.url()).toBe(undefined); }); - it("throws when creating a file with invalid data", () => { + it('throws when creating a file with invalid data', () => { expect(function () { - new ParseFile("parse.txt", 12); - }).toThrow("Cannot create a Parse.File with that data."); + new ParseFile('parse.txt', 12); + }).toThrow('Cannot create a Parse.File with that data.'); expect(function () { - new ParseFile("parse.txt", null); - }).toThrow("Cannot create a Parse.File with that data."); + new ParseFile('parse.txt', null); + }).toThrow('Cannot create a Parse.File with that data.'); expect(function () { - new ParseFile("parse.txt", "string"); - }).toThrow("Cannot create a Parse.File with that data."); + new ParseFile('parse.txt', 'string'); + }).toThrow('Cannot create a Parse.File with that data.'); }); - it("throws with invalid base64", () => { + it('throws with invalid base64', () => { expect(function () { b64Digit(65); - }).toThrow("Tried to encode large digit 65 in base64."); + }).toThrow('Tried to encode large digit 65 in base64.'); }); - it("returns secure url when specified", () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + it('returns secure url when specified', () => { + const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); 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'); }); }); - it("returns undefined when there is no url", () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + it('returns undefined when there is no url', () => { + const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); expect(file.url({ forceSecure: true })).toBeUndefined(); }); - it("updates fields when saved", () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); - expect(file.name()).toBe("parse.txt"); + it('updates fields when saved', () => { + 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) { expect(result).toBe(file); - expect(result.name()).toBe("parse.txt"); - expect(result.url()).toBe("http://files.parsetfss.com/a/parse.txt"); + expect(result.name()).toBe('parse.txt'); + expect(result.url()).toBe('http://files.parsetfss.com/a/parse.txt'); }); }); - it("updates fields when saved with uri", () => { - const file = new ParseFile("parse.png", { - uri: "https://example.com/image.png", + it('updates fields when saved with uri', () => { + const file = new ParseFile('parse.png', { + uri: 'https://example.com/image.png', }); - expect(file.name()).toBe("parse.png"); + expect(file.name()).toBe('parse.png'); expect(file.url()).toBe(undefined); 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"); + expect(result.name()).toBe('parse.png'); + expect(result.url()).toBe('http://files.parsetfss.com/a/parse.png'); }); }); - it("generates a JSON representation", () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + it('generates a JSON representation', () => { + const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); return file.save().then(function (result) { expect(result.toJSON()).toEqual({ - __type: "File", - name: "parse.txt", - url: "http://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', }); }); }); - it("can construct a file from a JSON object", () => { + it('can construct a file from a JSON object', () => { const f = ParseFile.fromJSON({ - __type: "File", - name: "parse.txt", - url: "http://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: '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(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", () => { - let a = new ParseFile("parse.txt", [61, 170, 236, 120]); - let b = new ParseFile("parse.txt", [61, 170, 236, 120]); + it('can test equality against another ParseFile', () => { + let a = new ParseFile('parse.txt', [61, 170, 236, 120]); + let b = new ParseFile('parse.txt', [61, 170, 236, 120]); expect(a.equals(a)).toBe(true); // unsaved files are never equal @@ -220,51 +215,48 @@ describe("ParseFile", () => { expect(b.equals(a)).toBe(false); a = ParseFile.fromJSON({ - __type: "File", - name: "parse.txt", - url: "http://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: '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", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', }); expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); b = ParseFile.fromJSON({ - __type: "File", - name: "parse.txt", - url: "http://files.parsetfss.com/b/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/b/parse.txt', }); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); }); - it("reports progress during save when source is a File", () => { - const file = new ParseFile( - "progress.txt", - new File(["Parse"], "progress.txt") - ); + it('reports progress during save when source is a File', () => { + const file = new ParseFile('progress.txt', new File(['Parse'], 'progress.txt')); const options = { progress: function () {}, }; - jest.spyOn(options, "progress"); + jest.spyOn(options, 'progress'); return file.save(options).then(function (f) { expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { - type: "upload", + type: 'upload', }); expect(f).toBe(file); - expect(f.name()).toBe("progress.txt"); - expect(f.url()).toBe("http://files.parsetfss.com/a/progress.txt"); + expect(f.name()).toBe('progress.txt'); + expect(f.url()).toBe('http://files.parsetfss.com/a/progress.txt'); }); }); - it("can cancel file upload", () => { + it('can cancel file upload', () => { const mockRequestTask = { abort: () => {}, }; @@ -276,12 +268,9 @@ describe("ParseFile", () => { 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"); + jest.spyOn(mockRequestTask, 'abort'); file.cancel(); expect(mockRequestTask.abort).toHaveBeenCalledTimes(0); @@ -292,170 +281,157 @@ describe("ParseFile", () => { expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); }); - it("should save file with metadata and tag options", async () => { + it('should save file with metadata and tag options', async () => { const fileController = { saveFile: jest.fn().mockResolvedValue({}), saveBase64: () => {}, download: () => {}, }; CoreManager.setFileController(fileController); - const file = new ParseFile( - "donald_duck.txt", - new File(["Parse"], "donald_duck.txt") - ); - file.addMetadata("foo", "bar"); - file.addTag("bar", "foo"); + const file = new ParseFile('donald_duck.txt', new File(['Parse'], 'donald_duck.txt')); + file.addMetadata('foo', 'bar'); + file.addTag('bar', 'foo'); await file.save(); expect(fileController.saveFile).toHaveBeenCalledWith( - "donald_duck.txt", + 'donald_duck.txt', { file: expect.any(File), - format: "file", - type: "", + format: 'file', + type: '', }, { - metadata: { foo: "bar" }, - tags: { bar: "foo" }, + metadata: { foo: 'bar' }, + tags: { bar: 'foo' }, requestTask: expect.any(Function), } ); }); - it("should create new ParseFile with metadata and tags", () => { - const metadata = { foo: "bar" }; - const tags = { bar: "foo" }; - const file = new ParseFile( - "parse.txt", - [61, 170, 236, 120], - "", - metadata, - tags - ); - expect(file._source.base64).toBe("ParseA=="); - expect(file._source.type).toBe(""); + it('should create new ParseFile with metadata and tags', () => { + const metadata = { foo: 'bar' }; + const tags = { bar: 'foo' }; + const file = new ParseFile('parse.txt', [61, 170, 236, 120], '', metadata, tags); + expect(file._source.base64).toBe('ParseA=='); + expect(file._source.type).toBe(''); expect(file.metadata()).toBe(metadata); expect(file.tags()).toBe(tags); }); - it("should set metadata", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.setMetadata({ foo: "bar" }); - expect(file.metadata()).toEqual({ foo: "bar" }); + it('should set metadata', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.setMetadata({ foo: 'bar' }); + expect(file.metadata()).toEqual({ foo: 'bar' }); }); - it("should set metadata key", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.addMetadata("foo", "bar"); - expect(file.metadata()).toEqual({ foo: "bar" }); + it('should set metadata key', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.addMetadata('foo', 'bar'); + expect(file.metadata()).toEqual({ foo: 'bar' }); }); - it("should not set metadata if key is not a string", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.addMetadata(10, ""); + it('should not set metadata if key is not a string', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.addMetadata(10, ''); expect(file.metadata()).toEqual({}); }); - it("should set tags", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.setTags({ foo: "bar" }); - expect(file.tags()).toEqual({ foo: "bar" }); + it('should set tags', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.setTags({ foo: 'bar' }); + expect(file.tags()).toEqual({ foo: 'bar' }); }); - it("should set tag key", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.addTag("foo", "bar"); - expect(file.tags()).toEqual({ foo: "bar" }); + it('should set tag key', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.addTag('foo', 'bar'); + expect(file.tags()).toEqual({ foo: 'bar' }); }); - it("should not set tag if key is not a string", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); - file.addTag(10, "bar"); + it('should not set tag if key is not a string', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); + file.addTag(10, 'bar'); expect(file.tags()).toEqual({}); }); }); -describe("FileController", () => { +describe('FileController', () => { beforeEach(() => { CoreManager.setFileController(defaultController); const request = function (method, path) { - const name = path.substr(path.indexOf("/") + 1); + 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 name = path.substr(path.indexOf("/") + 1); + 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 }); }); - it("saves files created with bytes", () => { - const file = new ParseFile("parse.txt", [61, 170, 236, 120]); + it('saves files created with bytes', () => { + const file = new ParseFile('parse.txt', [61, 170, 236, 120]); 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"); + expect(f.name()).toBe('parse.txt'); + expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); }); }); - it("saves files via ajax", () => { + it('saves files via ajax', () => { // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile("parse.txt", blob); - file._source.format = "file"; + const file = new ParseFile('parse.txt', blob); + file._source.format = 'file'; 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"); + expect(f.name()).toBe('parse.txt'); + expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); }); }); - it("saveUri with uri type", async () => { - const file = new ParseFile("parse.png", { - uri: "https://example.com/image.png", + 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 spy = jest.spyOn(defaultController, 'download').mockImplementationOnce(() => { + return Promise.resolve({ + base64: 'ParseA==', + contentType: 'image/png', }); + }); - const spy2 = jest.spyOn(defaultController, "saveBase64"); + const spy2 = jest.spyOn(defaultController, 'saveBase64'); await file.save(); expect(defaultController.download).toHaveBeenCalledTimes(1); expect(defaultController.saveBase64).toHaveBeenCalledTimes(1); - expect(defaultController.saveBase64.mock.calls[0][0]).toEqual("parse.png"); + 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", + 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 spy = jest - .spyOn(defaultController, "download") - .mockImplementationOnce(() => { - return Promise.resolve({}); - }); - const spy2 = jest.spyOn(defaultController, "saveBase64"); + const spy2 = jest.spyOn(defaultController, 'saveBase64'); await file.save(); expect(defaultController.download).toHaveBeenCalledTimes(1); expect(defaultController.saveBase64).toHaveBeenCalledTimes(0); @@ -463,36 +439,32 @@ describe("FileController", () => { spy2.mockRestore(); }); - it("download with base64 http", async () => { + it('download with base64 http', async () => { defaultController._setXHR(null); const mockResponse = Object.create(EventEmitter.prototype); EventEmitter.call(mockResponse); 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"); - expect(data.contentType).toBe("image/png"); + const data = await defaultController.download('http://example.com/image.png'); + expect(data.base64).toBe('base64String'); + expect(data.contentType).toBe('image/png'); expect(mockHttp.get).toHaveBeenCalledTimes(1); expect(mockHttps.get).toHaveBeenCalledTimes(0); spy.mockRestore(); }); - it("download with base64 http abort", async () => { + it('download with base64 http abort', async () => { defaultController._setXHR(null); const mockRequest = Object.create(EventEmitter.prototype); const mockResponse = Object.create(EventEmitter.prototype); @@ -500,56 +472,48 @@ describe("FileController", () => { EventEmitter.call(mockResponse); 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) => { - expect(data).toEqual({}); - }); - mockRequest.emit("abort"); + defaultController.download('http://example.com/image.png', options).then(data => { + expect(data).toEqual({}); + }); + mockRequest.emit('abort'); spy.mockRestore(); }); - it("download with base64 https", async () => { + it('download with base64 https', async () => { defaultController._setXHR(null); const mockResponse = Object.create(EventEmitter.prototype); EventEmitter.call(mockResponse); 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"); - expect(data.contentType).toBe("image/png"); + const data = await defaultController.download('https://example.com/image.png'); + expect(data.base64).toBe('base64String'); + expect(data.contentType).toBe('image/png'); expect(mockHttp.get).toHaveBeenCalledTimes(0); expect(mockHttps.get).toHaveBeenCalledTimes(1); spy.mockRestore(); }); - it("download with ajax", async () => { + it('download with ajax', async () => { const mockXHR = function () { return { DONE: 4, @@ -562,7 +526,7 @@ describe("FileController", () => { this.onreadystatechange(); }), getResponseHeader: function () { - return "image/png"; + return 'image/png'; }, }; }; @@ -570,15 +534,12 @@ describe("FileController", () => { const options = { requestTask: () => {}, }; - const data = await defaultController.download( - "https://example.com/image.png", - options - ); - expect(data.base64).toBe("ParseA=="); - expect(data.contentType).toBe("image/png"); + const data = await defaultController.download('https://example.com/image.png', options); + expect(data.base64).toBe('ParseA=='); + expect(data.contentType).toBe('image/png'); }); - it("download with ajax no response", async () => { + it('download with ajax no response', async () => { const mockXHR = function () { return { DONE: 4, @@ -591,7 +552,7 @@ describe("FileController", () => { this.onreadystatechange(); }), getResponseHeader: function () { - return "image/png"; + return 'image/png'; }, }; }; @@ -599,14 +560,11 @@ describe("FileController", () => { const options = { requestTask: () => {}, }; - const data = await defaultController.download( - "https://example.com/image.png", - options - ); + const data = await defaultController.download('https://example.com/image.png', options); expect(data).toEqual({}); }); - it("download with ajax abort", async () => { + it('download with ajax abort', async () => { const mockXHR = function () { return { open: jest.fn(), @@ -616,7 +574,7 @@ describe("FileController", () => { this.onreadystatechange(); }), getResponseHeader: function () { - return "image/png"; + return 'image/png'; }, abort: function () { this.status = 0; @@ -629,22 +587,20 @@ describe("FileController", () => { 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) => { - expect(data).toEqual({}); - }); + defaultController.download('https://example.com/image.png', options).then(data => { + expect(data).toEqual({}); + }); _requestTask.abort(); }); - it("download with ajax error", async () => { + it('download with ajax error', async () => { const mockXHR = function () { return { open: jest.fn(), send: jest.fn().mockImplementation(function () { - this.onerror("error thrown"); + this.onerror('error thrown'); }), }; }; @@ -653,185 +609,176 @@ describe("FileController", () => { requestTask: () => {}, }; try { - await defaultController.download( - "https://example.com/image.png", - options - ); + await defaultController.download('https://example.com/image.png', options); } catch (e) { - expect(e).toBe("error thrown"); + expect(e).toBe('error thrown'); } }); - it("download with xmlhttprequest unsupported", async () => { + it('download with xmlhttprequest unsupported', async () => { defaultController._setXHR(null); - process.env.PARSE_BUILD = "browser"; + process.env.PARSE_BUILD = 'browser'; try { - await defaultController.download("https://example.com/image.png"); + await defaultController.download('https://example.com/image.png'); } catch (e) { - expect(e).toBe( - "Cannot make a request: No definition of XMLHttpRequest was found." - ); + expect(e).toBe('Cannot make a request: No definition of XMLHttpRequest was found.'); } }); - it("getData", async () => { - const file = new ParseFile("parse.png", [61, 170, 236, 120]); + it('getData', async () => { + const file = new ParseFile('parse.png', [61, 170, 236, 120]); const data = await file.getData(); - expect(data).toBe("ParseA=="); + expect(data).toBe('ParseA=='); }); - it("getData unsaved file", async () => { - const file = new ParseFile("parse.png"); + it('getData unsaved file', async () => { + const file = new ParseFile('parse.png'); try { await file.getData(); } catch (e) { - expect(e.message).toBe("Cannot retrieve data for unsaved ParseFile."); + expect(e.message).toBe('Cannot retrieve data for unsaved ParseFile.'); } }); - it("getData via download", async () => { - const file = new ParseFile("parse.txt", { base64: "ParseA==" }); + it('getData via download', async () => { + const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); 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); - expect(data).toBe("ParseA=="); + expect(data).toBe('ParseA=='); spy.mockRestore(); }); - it("saves files via ajax with sessionToken option", () => { + it('saves files via ajax with sessionToken option', () => { const request = function (method, path) { - const name = path.substr(path.indexOf("/") + 1); + 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 name = path.substr(path.indexOf("/") + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile("parse.txt", blob); - file._source.format = "file"; - - 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"); - }); + const file = new ParseFile('parse.txt', blob); + file._source.format = 'file'; + + 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'); + }); }); - it("saves files via ajax currentUser sessionToken", () => { - CoreManager.set("UserController", { + it('saves files via ajax currentUser sessionToken', () => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "currentUserToken"; + return 'currentUserToken'; }, }); }, }); const request = function (method, path) { - const name = path.substr(path.indexOf("/") + 1); + 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 name = path.substr(path.indexOf("/") + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile("parse.txt", blob); - file._source.format = "file"; + const file = new ParseFile('parse.txt', blob); + file._source.format = 'file'; 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"); + expect(f.name()).toBe('parse.txt'); + expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); }); }); - it("should save file using saveFile with metadata and tags", async () => { - CoreManager.set("UserController", { + it('should save file using saveFile with metadata and tags', async () => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "currentUserToken"; + return 'currentUserToken'; }, }); }, }); const request = jest.fn((method, path) => { - const name = path.substr(path.indexOf("/") + 1); + 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 name = path.substr(path.indexOf("/") + 1); + 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 }); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile("parse.txt", blob); - file._source.format = "file"; - file.addMetadata("foo", "bar"); - file.addTag("bar", "foo"); + const file = new ParseFile('parse.txt', blob); + file._source.format = 'file'; + file.addMetadata('foo', 'bar'); + file.addTag('bar', 'foo'); const f = await file.save(); expect(f).toBe(file); - expect(f.name()).toBe("parse.txt"); - expect(f.url()).toBe("https://files.parsetfss.com/a/parse.txt"); + expect(f.name()).toBe('parse.txt'); + expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); expect(request).toHaveBeenCalledWith( - "POST", - "files/parse.txt", + 'POST', + 'files/parse.txt', { - base64: "NjExNzAyMzYxMjA=", + base64: 'NjExNzAyMzYxMjA=', fileData: { metadata: { - foo: "bar", + foo: 'bar', }, tags: { - bar: "foo", + bar: 'foo', }, }, }, @@ -839,33 +786,33 @@ describe("FileController", () => { ); }); - it("saves files via object saveAll options", async () => { + it('saves files via object saveAll options', async () => { const ajax = async () => {}; const request = jest.fn(async (method, path, data, options) => { - if (path.indexOf("files/") === 0) { - expect(options.sessionToken).toBe("testToken"); + if (path.indexOf('files/') === 0) { + expect(options.sessionToken).toBe('testToken'); return { - name: "parse.txt", - url: "http://files.parsetfss.com/a/parse.txt", + name: '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); // eslint-disable-next-line no-undef const blob = new Blob([61, 170, 236, 120]); - const file = new ParseFile("parse.txt", blob); - file._source.format = "file"; - const object = ParseObject.fromJSON({ className: "TestObject" }); - object.set("file", file); - await ParseObject.saveAll([object], { sessionToken: "testToken" }); + const file = new ParseFile('parse.txt', blob); + file._source.format = 'file'; + const object = ParseObject.fromJSON({ className: 'TestObject' }); + object.set('file', file); + await ParseObject.saveAll([object], { sessionToken: 'testToken' }); expect(request).toHaveBeenCalled(); }); - it("should throw error if file deleted without name", async (done) => { - const file = new ParseFile("", [1, 2, 3]); + it('should throw error if file deleted without name', async done => { + const file = new ParseFile('', [1, 2, 3]); try { await file.destroy(); } catch (e) { @@ -874,101 +821,80 @@ describe("FileController", () => { } }); - it("should delete file", async () => { - const file = new ParseFile("filename", [1, 2, 3]); - const ajax = jest.fn().mockResolvedValueOnce({ foo: "bar" }); + it('should delete file', async () => { + const file = new ParseFile('filename', [1, 2, 3]); + const ajax = jest.fn().mockResolvedValueOnce({ foo: 'bar' }); CoreManager.setRESTController({ ajax, request: () => {} }); 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, - } - ); + expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { + '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]); + 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.")) - ); + .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, - } - ); + expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { + 'X-Parse-Application-ID': null, + 'X-Parse-Master-Key': null, + }); expect(handleError).toHaveBeenCalled(); }); - it("should handle delete file error invalid server response", async () => { - const file = new ParseFile("filename", [1, 2, 3]); + it('should handle delete file error invalid server response', async () => { + const file = new ParseFile('filename', [1, 2, 3]); const response = null; const ajax = jest.fn().mockResolvedValueOnce(Promise.reject(response)); 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, - } - ); + expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { + 'X-Parse-Application-ID': null, + 'X-Parse-Master-Key': null, + }); expect(handleError).not.toHaveBeenCalled(); }); - it("controller saveFile format errors", async () => { + 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." - ); + expect(e.message).toBe('saveFile can only be used with File-type sources.'); } }); - it("controller saveBase64 format errors", async () => { + 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." - ); + expect(e.message).toBe('saveBase64 can only be used with Base64-type sources.'); } }); - it("controller saveFile file reader errors", async () => { + it('controller saveFile file reader errors', async () => { const fileReader = global.FileReader; class FileReader { readAsDataURL() { - this.onerror("Could not load file."); + this.onerror('Could not load file.'); } } 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."); + expect(e).toBe('Could not load file.'); } global.FileReader = fileReader; }); diff --git a/src/__tests__/ParseGeoPoint-test.js b/src/__tests__/ParseGeoPoint-test.js index a4555e083..2f3e65029 100644 --- a/src/__tests__/ParseGeoPoint-test.js +++ b/src/__tests__/ParseGeoPoint-test.js @@ -9,9 +9,9 @@ jest.autoMockOff(); -const ParseGeoPoint = require("../ParseGeoPoint").default; +const ParseGeoPoint = require('../ParseGeoPoint').default; global.navigator.geolocation = { - getCurrentPosition: (cb) => { + getCurrentPosition: cb => { return cb({ coords: { latitude: 10, @@ -21,8 +21,8 @@ global.navigator.geolocation = { }, }; -describe("GeoPoint", () => { - it("can be constructed from various inputs", () => { +describe('GeoPoint', () => { + it('can be constructed from various inputs', () => { let point = new ParseGeoPoint(); expect(point.latitude).toBe(0); expect(point.longitude).toBe(0); @@ -40,23 +40,23 @@ describe("GeoPoint", () => { expect(point.longitude).toBe(88); }); - it("throws when created with non numbers values", () => { + it('throws when created with non numbers values', () => { [ [NaN, NaN], [false, true], - ["29", "10"], - [29, "10"], - ["29", 10], - [["29", "10"]], - [{ latitude: "29", longitude: "10" }], - ].forEach((case_test) => { + ['29', '10'], + [29, '10'], + ['29', 10], + [['29', '10']], + [{ latitude: '29', longitude: '10' }], + ].forEach(case_test => { expect(function () { new ParseGeoPoint(...case_test); - }).toThrow("GeoPoint latitude and longitude must be valid numbers"); + }).toThrow('GeoPoint latitude and longitude must be valid numbers'); }); }); - it("can set latitude and longitude", () => { + it('can set latitude and longitude', () => { const point = new ParseGeoPoint(); expect(point.latitude).toBe(0); expect(point.longitude).toBe(0); @@ -74,7 +74,7 @@ describe("GeoPoint", () => { expect(point.longitude).toBe(14.9); }); - it("throws for points out of bounds", () => { + it('throws for points out of bounds', () => { expect(() => { new ParseGeoPoint(90.01, 0.0); }).toThrow(); @@ -92,7 +92,7 @@ describe("GeoPoint", () => { }).toThrow(); }); - it("can calculate distance in radians", () => { + it('can calculate distance in radians', () => { const d2r = Math.PI / 180.0; const pointA = new ParseGeoPoint(); const pointB = new ParseGeoPoint(); @@ -149,7 +149,7 @@ describe("GeoPoint", () => { expect(pointB.radiansTo(pointA)).toBeCloseTo(1.85, 2); }); - it("can calculate distances in mi and km", () => { + it('can calculate distances in mi and km', () => { // [SAC] 38.52 -121.50 Sacramento,CA const sacramento = new ParseGeoPoint(38.52, -121.5); @@ -199,7 +199,7 @@ describe("GeoPoint", () => { expect(sacramento.milesTo(vorkuta)).toBeCloseTo(5159.7, -3); }); - it("can test equality against another GeoPoint", () => { + it('can test equality against another GeoPoint', () => { let a = new ParseGeoPoint(40, 40); expect(a.equals(a)).toBe(true); @@ -225,7 +225,7 @@ describe("GeoPoint", () => { expect(b.equals(a)).toBe(false); }); - it("can get current location", async () => { + it('can get current location', async () => { const geoPoint = ParseGeoPoint.current(); expect(geoPoint.latitude).toBe(10); expect(geoPoint.longitude).toBe(20); diff --git a/src/__tests__/ParseInstallation-test.js b/src/__tests__/ParseInstallation-test.js index 938beac6c..20c01d007 100644 --- a/src/__tests__/ParseInstallation-test.js +++ b/src/__tests__/ParseInstallation-test.js @@ -1,28 +1,28 @@ -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParseInstallation"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParseInstallation'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../UniqueInstanceStateController'); -const ParseInstallation = require("../ParseInstallation").default; +const ParseInstallation = require('../ParseInstallation').default; -describe("ParseInstallation", () => { - it("can create ParseInstallation", () => { +describe('ParseInstallation', () => { + it('can create ParseInstallation', () => { let installation = new ParseInstallation(); - expect(installation.className).toBe("_Installation"); + expect(installation.className).toBe('_Installation'); installation = new ParseInstallation({}); - expect(installation.className).toBe("_Installation"); + expect(installation.className).toBe('_Installation'); - installation = new ParseInstallation({ deviceToken: "token" }); - expect(installation.get("deviceToken")).toBe("token"); + installation = new ParseInstallation({ deviceToken: 'token' }); + 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 6896f17b9..7f4a52643 100644 --- a/src/__tests__/ParseLiveQuery-test.js +++ b/src/__tests__/ParseLiveQuery-test.js @@ -7,195 +7,186 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../ParseLiveQuery"); -jest.dontMock("../CoreManager"); -jest.dontMock("../InstallationController"); -jest.dontMock("../LiveQueryClient"); -jest.dontMock("../LiveQuerySubscription"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseQuery"); -jest.dontMock("../EventEmitter"); -jest.dontMock("../promiseUtils"); +jest.dontMock('../ParseLiveQuery'); +jest.dontMock('../CoreManager'); +jest.dontMock('../InstallationController'); +jest.dontMock('../LiveQueryClient'); +jest.dontMock('../LiveQuerySubscription'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseQuery'); +jest.dontMock('../EventEmitter'); +jest.dontMock('../promiseUtils'); // Forces the loading -const LiveQuery = require("../ParseLiveQuery").default; -const CoreManager = require("../CoreManager"); -const ParseQuery = require("../ParseQuery").default; -const LiveQuerySubscription = require("../LiveQuerySubscription").default; +const LiveQuery = require('../ParseLiveQuery').default; +const CoreManager = require('../CoreManager'); +const ParseQuery = require('../ParseQuery').default; +const LiveQuerySubscription = require('../LiveQuerySubscription').default; const mockLiveQueryClient = { open: jest.fn(), close: jest.fn(), }; -describe("ParseLiveQuery", () => { +describe('ParseLiveQuery', () => { beforeEach(() => { const controller = CoreManager.getLiveQueryController(); controller._clearCachedDefaultClient(); - CoreManager.set("InstallationController", { + CoreManager.set('InstallationController', { currentInstallationId() { - return Promise.resolve("1234"); + return Promise.resolve('1234'); }, }); }); - it("fails with an invalid livequery server url", (done) => { - CoreManager.set("UserController", { + it('fails with an invalid livequery server url', done => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(undefined); }, }); - CoreManager.set("LIVEQUERY_SERVER_URL", "notaurl"); + 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" + 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' ); done(); }); }); - it("initializes the client", (done) => { - CoreManager.set("UserController", { + 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"); + 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) => { - expect(client.serverURL).toBe("wss://live.example.com/parse"); - expect(client.applicationId).toBe("appid"); - expect(client.javascriptKey).toBe("jskey"); + controller.getDefaultLiveQueryClient().then(client => { + expect(client.serverURL).toBe('wss://live.example.com/parse'); + expect(client.applicationId).toBe('appid'); + expect(client.javascriptKey).toBe('jskey'); expect(client.sessionToken).toBe(undefined); - expect(client.installationId).toBe("1234"); + expect(client.installationId).toBe('1234'); expect(client.additionalProperties).toBe(true); done(); }); }); - it("automatically generates a ws websocket url", (done) => { - CoreManager.set("UserController", { + 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); + 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) => { - expect(client.serverURL).toBe("ws://api.parse.com/1"); - expect(client.applicationId).toBe("appid"); - expect(client.javascriptKey).toBe("jskey"); + controller.getDefaultLiveQueryClient().then(client => { + expect(client.serverURL).toBe('ws://api.parse.com/1'); + expect(client.applicationId).toBe('appid'); + expect(client.javascriptKey).toBe('jskey'); expect(client.sessionToken).toBe(undefined); done(); }); }); - it("automatically generates a wss websocket url", (done) => { - CoreManager.set("UserController", { + 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); + 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) => { - expect(client.serverURL).toBe("wss://api.parse.com/1"); - expect(client.applicationId).toBe("appid"); - expect(client.javascriptKey).toBe("jskey"); + controller.getDefaultLiveQueryClient().then(client => { + expect(client.serverURL).toBe('wss://api.parse.com/1'); + expect(client.applicationId).toBe('appid'); + expect(client.javascriptKey).toBe('jskey'); expect(client.sessionToken).toBe(undefined); done(); }); }); - it("populates the session token", (done) => { - CoreManager.set("UserController", { + it('populates the session token', done => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - CoreManager.set("APPLICATION_ID", "appid"); - CoreManager.set("JAVASCRIPT_KEY", "jskey"); - CoreManager.set("LIVEQUERY_SERVER_URL", null); + CoreManager.set('APPLICATION_ID', 'appid'); + CoreManager.set('JAVASCRIPT_KEY', 'jskey'); + CoreManager.set('LIVEQUERY_SERVER_URL', null); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then((client) => { - expect(client.serverURL).toBe("wss://api.parse.com/1"); - expect(client.applicationId).toBe("appid"); - expect(client.javascriptKey).toBe("jskey"); - expect(client.sessionToken).toBe("token"); + controller.getDefaultLiveQueryClient().then(client => { + expect(client.serverURL).toBe('wss://api.parse.com/1'); + expect(client.applicationId).toBe('appid'); + expect(client.javascriptKey).toBe('jskey'); + expect(client.sessionToken).toBe('token'); done(); }); }); - it("handle LiveQueryClient events", async () => { - const spy = jest.spyOn(LiveQuery, "emit"); + it('handle LiveQueryClient events', async () => { + const spy = jest.spyOn(LiveQuery, 'emit'); - CoreManager.set("UserController", { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - CoreManager.set("APPLICATION_ID", "appid"); - CoreManager.set("JAVASCRIPT_KEY", "jskey"); - CoreManager.set("LIVEQUERY_SERVER_URL", null); + CoreManager.set('APPLICATION_ID', 'appid'); + CoreManager.set('JAVASCRIPT_KEY', 'jskey'); + CoreManager.set('LIVEQUERY_SERVER_URL', null); const controller = CoreManager.getLiveQueryController(); const client = await controller.getDefaultLiveQueryClient(); - client.emit("error", "error thrown"); - client.emit("open"); - client.emit("close"); - expect(spy.mock.calls[0]).toEqual(["error", "error thrown"]); - expect(spy.mock.calls[1]).toEqual(["open"]); - expect(spy.mock.calls[2]).toEqual(["close"]); + client.emit('error', 'error thrown'); + client.emit('open'); + client.emit('close'); + expect(spy.mock.calls[0]).toEqual(['error', 'error thrown']); + expect(spy.mock.calls[1]).toEqual(['open']); + expect(spy.mock.calls[2]).toEqual(['close']); spy.mockRestore(); }); - it("subscribes to all subscription events", (done) => { - CoreManager.set("UserController", { + it('subscribes to all subscription events', done => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - CoreManager.set("APPLICATION_ID", "appid"); - CoreManager.set("JAVASCRIPT_KEY", "jskey"); - CoreManager.set("LIVEQUERY_SERVER_URL", null); + CoreManager.set('APPLICATION_ID', 'appid'); + CoreManager.set('JAVASCRIPT_KEY', 'jskey'); + CoreManager.set('LIVEQUERY_SERVER_URL', null); 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; }); @@ -213,29 +204,29 @@ describe("ParseLiveQuery", () => { 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) { @@ -245,24 +236,24 @@ describe("ParseLiveQuery", () => { }); }); - it("should not throw on usubscribe", (done) => { - CoreManager.set("UserController", { + it('should not throw on usubscribe', done => { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - const query = new ParseQuery("ObjectType"); - query.equalTo("test", "value"); - const subscription = new LiveQuerySubscription("0", query, "token"); + const query = new ParseQuery('ObjectType'); + query.equalTo('test', 'value'); + const subscription = new LiveQuerySubscription('0', query, 'token'); subscription.unsubscribe().then(done).catch(done.fail); }); - it("can handle LiveQuery open event", async () => { - jest.spyOn(mockLiveQueryClient, "open"); + it('can handle LiveQuery open event', async () => { + jest.spyOn(mockLiveQueryClient, 'open'); const controller = CoreManager.getLiveQueryController(); controller.setDefaultLiveQueryClient(mockLiveQueryClient); @@ -270,8 +261,8 @@ describe("ParseLiveQuery", () => { expect(mockLiveQueryClient.open).toHaveBeenCalled(); }); - it("can handle LiveQuery close event", async () => { - jest.spyOn(mockLiveQueryClient, "close"); + it('can handle LiveQuery close event', async () => { + jest.spyOn(mockLiveQueryClient, 'close'); const controller = CoreManager.getLiveQueryController(); controller.setDefaultLiveQueryClient(mockLiveQueryClient); @@ -279,9 +270,9 @@ describe("ParseLiveQuery", () => { expect(mockLiveQueryClient.close).toHaveBeenCalled(); }); - it("can handle LiveQuery error event", async () => { + it('can handle LiveQuery error event', async () => { try { - LiveQuery.emit("error"); + LiveQuery.emit('error'); expect(true).toBe(true); } catch (error) { // Should not throw error diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index ff930f4b7..892e6fb11 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -7,37 +7,37 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../arrayContainsObject"); -jest.dontMock("../canBeSerialized"); -jest.dontMock("../CoreManager"); -jest.dontMock("../promiseUtils"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../equals"); -jest.dontMock("../escape"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../parseDate"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParsePolygon"); -jest.dontMock("../ParseRelation"); -jest.dontMock("../RESTController"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../TaskQueue"); -jest.dontMock("../unique"); -jest.dontMock("../UniqueInstanceStateController"); -jest.dontMock("../unsavedChildren"); -jest.dontMock("../ParseACL"); -jest.dontMock("../LocalDatastore"); - -jest.mock("uuid/v4", () => { +jest.dontMock('../arrayContainsObject'); +jest.dontMock('../canBeSerialized'); +jest.dontMock('../CoreManager'); +jest.dontMock('../promiseUtils'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../equals'); +jest.dontMock('../escape'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../parseDate'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParsePolygon'); +jest.dontMock('../ParseRelation'); +jest.dontMock('../RESTController'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../TaskQueue'); +jest.dontMock('../unique'); +jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock('../unsavedChildren'); +jest.dontMock('../ParseACL'); +jest.dontMock('../LocalDatastore'); + +jest.mock('uuid/v4', () => { let value = 0; return () => value++; }); -jest.dontMock("./test_helpers/mockXHR"); +jest.dontMock('./test_helpers/mockXHR'); jest.useFakeTimers(); @@ -54,28 +54,22 @@ mockRelation.prototype.add = function (obj) { }; mockRelation.prototype.toJSON = function () { return { - __type: "Relation", + __type: 'Relation', className: this.targetClassName, }; }; 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; @@ -84,14 +78,14 @@ mockRelation.prototype._ensureParentAndKey = function (parent, key) { this.parent = parent; } }; -jest.setMock("../ParseRelation", mockRelation); +jest.setMock('../ParseRelation', mockRelation); const mockQuery = function (className) { this.className = className; }; mockQuery.prototype.containedIn = function (field, ids) { this.results = []; - ids.forEach((id) => { + ids.forEach(id => { this.results.push( ParseObject.fromJSON({ className: this.className, @@ -115,9 +109,9 @@ mockQuery.prototype.get = function (id) { }); return Promise.resolve(object); }; -jest.setMock("../ParseQuery", mockQuery); +jest.setMock('../ParseQuery', mockQuery); -import { DEFAULT_PIN, PIN_PREFIX } from "../LocalDatastoreUtils"; +import { DEFAULT_PIN, PIN_PREFIX } from '../LocalDatastoreUtils'; const mockLocalDatastore = { isEnabled: false, @@ -138,118 +132,118 @@ const mockLocalDatastore = { getKeyForObject: jest.fn(), checkIfEnabled: jest.fn(() => { if (!mockLocalDatastore.isEnabled) { - console.error("Parse.enableLocalDatastore() must be called first"); + console.error('Parse.enableLocalDatastore() must be called first'); } return mockLocalDatastore.isEnabled; }), }; -jest.setMock("../LocalDatastore", mockLocalDatastore); - -const CoreManager = require("../CoreManager"); -const ParseACL = require("../ParseACL").default; -const ParseError = require("../ParseError").default; -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParsePolygon = require("../ParsePolygon").default; -const ParseObject = require("../ParseObject").default; -const ParseOp = require("../ParseOp"); -const RESTController = require("../RESTController"); -const SingleInstanceStateController = require("../SingleInstanceStateController"); -const unsavedChildren = require("../unsavedChildren").default; - -const mockXHR = require("./test_helpers/mockXHR"); +jest.setMock('../LocalDatastore', mockLocalDatastore); + +const CoreManager = require('../CoreManager'); +const ParseACL = require('../ParseACL').default; +const ParseError = require('../ParseError').default; +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParsePolygon = require('../ParsePolygon').default; +const ParseObject = require('../ParseObject').default; +const ParseOp = require('../ParseOp'); +const RESTController = require('../RESTController'); +const SingleInstanceStateController = require('../SingleInstanceStateController'); +const unsavedChildren = require('../unsavedChildren').default; + +const mockXHR = require('./test_helpers/mockXHR'); CoreManager.setLocalDatastore(mockLocalDatastore); CoreManager.setRESTController(RESTController); CoreManager.setInstallationController({ currentInstallationId() { - return Promise.resolve("iid"); + return Promise.resolve('iid'); }, }); -CoreManager.set("APPLICATION_ID", "A"); -CoreManager.set("JAVASCRIPT_KEY", "B"); -CoreManager.set("MASTER_KEY", "C"); -CoreManager.set("VERSION", "V"); +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)); + return new Promise(resolve => setImmediate(resolve)); } -describe("ParseObject", () => { +describe('ParseObject', () => { beforeEach(() => { ParseObject.enableSingleInstance(); jest.clearAllMocks(); }); - it("is initially created with no Id", () => { - const o = new ParseObject("Item"); + it('is initially created with no Id', () => { + const o = new ParseObject('Item'); expect(o.id).toBe(undefined); expect(o._localId).toBe(undefined); expect(o.dirty()).toBe(true); }); - it("can be created with initial attributes", () => { + it('can be created with initial attributes', () => { const o = new ParseObject({ - className: "Item", + className: 'Item', value: 12, }); - expect(o.className).toBe("Item"); + expect(o.className).toBe('Item'); expect(o.attributes).toEqual({ value: 12 }); }); - it("can be created with attributes parameter", () => { - const o = new ParseObject("Item", { + it('can be created with attributes parameter', () => { + const o = new ParseObject('Item', { value: 12, }); - expect(o.className).toBe("Item"); + expect(o.className).toBe('Item'); expect(o.attributes).toEqual({ value: 12 }); }); - it("can ignore setting invalid key", () => { - const o = new ParseObject("Item"); + it('can ignore setting invalid key', () => { + const o = new ParseObject('Item'); const o2 = o.set(1234); expect(o).toEqual(o2); }); - it("can ignore setting createdAt", () => { - const o = new ParseObject("Item"); - o.set("createdAt", "1234"); - expect(o.get("createdAt")).toEqual(undefined); + it('can ignore setting createdAt', () => { + const o = new ParseObject('Item'); + o.set('createdAt', '1234'); + expect(o.get('createdAt')).toEqual(undefined); }); - it("can handle setting relationOp", () => { - const child = new ParseObject("Child"); - child.id = "child1234"; - const relationOpJSON = { __op: "AddRelation", objects: [child] }; - const o = new ParseObject("Item"); - o.set("friends", relationOpJSON); + it('can handle setting relationOp', () => { + const child = new ParseObject('Child'); + child.id = 'child1234'; + const relationOpJSON = { __op: 'AddRelation', objects: [child] }; + const o = new ParseObject('Item'); + o.set('friends', relationOpJSON); o._handleSaveResponse({}); - expect(o.get("friends").targetClassName).toBe("Child"); + expect(o.get('friends').targetClassName).toBe('Child'); }); - it("cannot create with invalid attributes", () => { + it('cannot create with invalid attributes', () => { expect(() => { new ParseObject({ - className: "Item", - "invalid#name": "foo", + className: 'Item', + 'invalid#name': 'foo', }); }).toThrow("Can't create an invalid Parse Object"); }); - it("can ignore validation if ignoreValidation option is provided", () => { + it('can ignore validation if ignoreValidation option is provided', () => { class ValidatedObject extends ParseObject { validate(attrs) { - if (attrs.hasOwnProperty("badAttr")) { - return "you have the bad attr"; + if (attrs.hasOwnProperty('badAttr')) { + return 'you have the bad attr'; } } } const o = new ValidatedObject( { - className: "Item", + className: 'Item', value: 12, badAttr: true, }, @@ -260,652 +254,636 @@ describe("ParseObject", () => { expect(o.attributes.badAttr).toBe(true); }); - it("can be inflated from server JSON", () => { + it('can be inflated from server JSON', () => { const json = { - className: "Item", - createdAt: "2013-12-14T04:51:19Z", - objectId: "I1", - size: "medium", + className: 'Item', + createdAt: '2013-12-14T04:51:19Z', + objectId: 'I1', + size: 'medium', }; const o = ParseObject.fromJSON(json); - expect(o.className).toBe("Item"); - expect(o.id).toBe("I1"); + expect(o.className).toBe('Item'); + expect(o.id).toBe('I1'); expect(o.attributes).toEqual({ - size: "medium", + size: 'medium', createdAt: 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); }); - it("can override old data when inflating from the server", () => { + it('can override old data when inflating from the server', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "I01", - size: "small", + className: 'Item', + objectId: 'I01', + size: 'small', }); - expect(o.get("size")).toBe("small"); + expect(o.get('size')).toBe('small'); const o2 = ParseObject.fromJSON( { - className: "Item", - objectId: "I01", + 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); + expect(o.get('disabled')).toBe(true); + expect(o.get('size')).toBe(undefined); + expect(o.has('size')).toBe(false); - expect(o2.get("disabled")).toBe(true); - expect(o2.get("size")).toBe(undefined); - expect(o2.has("size")).toBe(false); + expect(o2.get('disabled')).toBe(true); + expect(o2.get('size')).toBe(undefined); + expect(o2.has('size')).toBe(false); }); - it("is given a local Id once dirtied", () => { - const o = new ParseObject("Item"); - o.set("size", "small"); + it('is given a local Id once dirtied', () => { + const o = new ParseObject('Item'); + o.set('size', 'small'); expect(o._localId).toBeTruthy(); }); - it("has a read-only attributes property", () => { - const o = new ParseObject("Item"); - o.set("size", "small"); + it('has a read-only attributes property', () => { + const o = new ParseObject('Item'); + o.set('size', 'small'); expect(function () { - o.attributes.size = "large"; + o.attributes.size = 'large'; }).toThrow(); }); - it("exposes read-only createdAt and updatedAt", () => { - const o = new ParseObject("Item"); - expect(o.get("createdAt")).toBe(undefined); - expect(o.get("updatedAt")).toBe(undefined); + it('exposes read-only createdAt and updatedAt', () => { + const o = new ParseObject('Item'); + expect(o.get('createdAt')).toBe(undefined); + expect(o.get('updatedAt')).toBe(undefined); const created = new Date(); const updated = new Date(); o._finishFetch({ - objectId: "O1", - createdAt: { __type: "Date", iso: created.toISOString() }, - updatedAt: { __type: "Date", iso: updated.toISOString() }, + objectId: 'O1', + createdAt: { __type: 'Date', iso: created.toISOString() }, + updatedAt: { __type: 'Date', iso: updated.toISOString() }, }); - expect(o.get("createdAt")).toEqual(created); - expect(o.get("updatedAt")).toEqual(updated); + expect(o.get('createdAt')).toEqual(created); + expect(o.get('updatedAt')).toEqual(updated); expect(o.createdAt).toEqual(created); expect(o.updatedAt).toEqual(updated); }); - it("fetch ACL from serverData", () => { + it('fetch ACL from serverData', () => { const ACL = new ParseACL({ user1: { read: true } }); - const o = new ParseObject("Item"); + const o = new ParseObject('Item'); o._finishFetch({ - objectId: "O1", + objectId: 'O1', ACL: { user1: { read: true } }, }); expect(o.getACL()).toEqual(ACL); }); - it("can be rendered to JSON", () => { - let o = new ParseObject("Item"); + it('can be rendered to JSON', () => { + let o = new ParseObject('Item'); o.set({ - size: "large", + size: 'large', inStock: 18, }); expect(o.toJSON()).toEqual({ - size: "large", + size: 'large', inStock: 18, }); - o = new ParseObject("Item"); + o = new ParseObject('Item'); o._finishFetch({ - objectId: "O2", - size: "medium", + objectId: 'O2', + size: 'medium', inStock: 12, }); - expect(o.id).toBe("O2"); + expect(o.id).toBe('O2'); expect(o.toJSON()).toEqual({ - objectId: "O2", - size: "medium", + objectId: 'O2', + size: 'medium', inStock: 12, }); }); - it("encodes createdAt and updatedAt fields as strings", () => { + it('encodes createdAt and updatedAt fields as strings', () => { const o = ParseObject.fromJSON({ - id: "hasDates", - className: "Item", + id: 'hasDates', + className: 'Item', createdAt: { - __type: "Date", + __type: 'Date', iso: new Date(Date.UTC(2015, 0, 1)).toJSON(), }, updatedAt: { - __type: "Date", + __type: 'Date', iso: new Date(Date.UTC(2015, 0, 1)).toJSON(), }, - foo: "bar", + foo: 'bar', }); expect(o.toJSON()).toEqual({ - id: "hasDates", - createdAt: "2015-01-01T00:00:00.000Z", - updatedAt: "2015-01-01T00:00:00.000Z", - foo: "bar", + id: 'hasDates', + createdAt: '2015-01-01T00:00:00.000Z', + updatedAt: '2015-01-01T00:00:00.000Z', + foo: 'bar', }); }); - it("can convert to a pointer", () => { - const o = new ParseObject("Item"); + it('can convert to a pointer', () => { + const o = new ParseObject('Item'); expect(function () { o.toPointer(); - }).toThrow("Cannot create a pointer to an unsaved ParseObject"); - o.id = "anObjectId"; + }).toThrow('Cannot create a pointer to an unsaved ParseObject'); + o.id = 'anObjectId'; expect(o.toPointer()).toEqual({ - __type: "Pointer", - className: "Item", - objectId: "anObjectId", + __type: 'Pointer', + className: 'Item', + objectId: 'anObjectId', }); }); - it("can convert to a offline pointer", () => { - const o = new ParseObject("Item"); - o.id = "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"); - o._localId = "local1234"; + }).toThrow('Cannot create a offline pointer to a saved ParseObject'); + o._localId = 'local1234'; expect(o.toOfflinePointer()).toEqual({ - __type: "Object", - className: "Item", - _localId: "local1234", + __type: 'Object', + className: 'Item', + _localId: 'local1234', }); }); - it("can test equality against another ParseObject", () => { - const a = new ParseObject("Item"); + it('can test equality against another ParseObject', () => { + const a = new ParseObject('Item'); expect(a.equals(a)).toBe(true); - const b = new ParseObject("Item"); + const b = new ParseObject('Item'); expect(a.equals(b)).toBe(false); expect(b.equals(a)).toBe(false); - a.id = "anObjectId"; - b.id = "anObjectId"; + a.id = 'anObjectId'; + b.id = 'anObjectId'; expect(a.equals(b)).toBe(true); expect(b.equals(a)).toBe(true); }); - it("can set a field", () => { - const o = new ParseObject("Person"); + it('can set a field', () => { + const o = new ParseObject('Person'); expect(o.attributes).toEqual({}); - o.set("name", "Will"); - expect(o.attributes).toEqual({ name: "Will" }); - expect(o.op("name") instanceof SetOp).toBe(true); - expect(o.dirtyKeys()).toEqual(["name"]); + o.set('name', 'Will'); + expect(o.attributes).toEqual({ name: 'Will' }); + expect(o.op('name') instanceof SetOp).toBe(true); + expect(o.dirtyKeys()).toEqual(['name']); expect(o.dirty()).toBe(true); - expect(o.dirty("name")).toBe(true); - expect(o._getSaveJSON()).toEqual({ name: "Will" }); + expect(o.dirty('name')).toBe(true); + expect(o._getSaveJSON()).toEqual({ name: 'Will' }); // set multiple fields at once - o.set({ name: "William", behavior: "formal" }); - expect(o.attributes).toEqual({ name: "William", behavior: "formal" }); + o.set({ name: 'William', behavior: 'formal' }); + expect(o.attributes).toEqual({ name: 'William', behavior: 'formal' }); }); - it("can set id with the objectId attribute", () => { - const o = new ParseObject("Person"); + it('can set id with the objectId attribute', () => { + const o = new ParseObject('Person'); expect(o.attributes).toEqual({}); expect(o.id).toBe(undefined); - o.set({ objectId: "oid" }); + o.set({ objectId: 'oid' }); expect(o.attributes).toEqual({}); - expect(o.id).toBe("oid"); + expect(o.id).toBe('oid'); }); - it("can get an escaped version of a field", () => { - const o = new ParseObject("Person"); - o.set("age", 28); - o.set("phoneProvider", "AT&T"); - o.set("objectField", { toString: "hacking" }); - expect(o.escape("notSet")).toBe(""); - expect(o.escape("age")).toBe("28"); - expect(o.escape("phoneProvider")).toBe("AT&T"); - expect(o.escape("objectField")).toBe(""); + it('can get an escaped version of a field', () => { + const o = new ParseObject('Person'); + o.set('age', 28); + o.set('phoneProvider', 'AT&T'); + o.set('objectField', { toString: 'hacking' }); + expect(o.escape('notSet')).toBe(''); + expect(o.escape('age')).toBe('28'); + expect(o.escape('phoneProvider')).toBe('AT&T'); + expect(o.escape('objectField')).toBe(''); }); - it("can tell if it has an attribute", () => { - const o = new ParseObject("Person"); - o.set("age", 28); - expect(o.has("name")).toBe(false); - expect(o.has("age")).toBe(true); + it('can tell if it has an attribute', () => { + const o = new ParseObject('Person'); + o.set('age', 28); + expect(o.has('name')).toBe(false); + expect(o.has('age')).toBe(true); }); - it("can tell if a field is dirty", () => { - const o = new ParseObject("Person"); + it('can tell if a field is dirty', () => { + const o = new ParseObject('Person'); o._finishFetch({ - objectId: "p99", + objectId: 'p99', age: 28, human: true, - objectField: { foo: "bar" }, + objectField: { foo: 'bar' }, }); expect(o.dirty()).toBe(false); - expect(o.dirty("age")).toBe(false); - expect(o.dirty("human")).toBe(false); - expect(o.dirty("unset")).toBe(false); - expect(o.dirty("objectField")).toBe(false); - o.set("human", false); - o.set("objectField", { foo: "baz" }); + expect(o.dirty('age')).toBe(false); + expect(o.dirty('human')).toBe(false); + expect(o.dirty('unset')).toBe(false); + expect(o.dirty('objectField')).toBe(false); + o.set('human', false); + o.set('objectField', { foo: 'baz' }); expect(o.dirty()).toBe(true); - expect(o.dirty("age")).toBe(false); - 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"); - o.id = "anObjectId"; - o.set("name", "Will"); - expect(o.attributes).toEqual({ name: "Will" }); - o.unset("name"); + expect(o.dirty('age')).toBe(false); + 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'); + o.id = 'anObjectId'; + o.set('name', 'Will'); + expect(o.attributes).toEqual({ name: 'Will' }); + o.unset('name'); expect(o.attributes).toEqual({}); // Even when you unset an unsaved set, it's still dirty - expect(o.op("name") instanceof UnsetOp).toBe(true); + expect(o.op('name') instanceof UnsetOp).toBe(true); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual(["name"]); + expect(o.dirtyKeys()).toEqual(['name']); - const o2 = new ParseObject("Person"); + const o2 = new ParseObject('Person'); o2._finishFetch({ - objectId: "P1", - name: "Will", + objectId: 'P1', + name: 'Will', }); - expect(o2.attributes).toEqual({ name: "Will" }); - o2.unset("name"); + expect(o2.attributes).toEqual({ name: 'Will' }); + o2.unset('name'); expect(o2.attributes).toEqual({}); }); - it("can clear all fields", () => { - const o = new ParseObject("Person"); + it('can clear all fields', () => { + const o = new ParseObject('Person'); o._finishFetch({ - objectId: "P95", - createdAt: { __type: "Date", iso: new Date().toISOString() }, - updatedAt: { __type: "Date", iso: new Date().toISOString() }, - }); - o.set({ a: "a", b: "b", c: "c" }); - expect(o.dirty("a")).toBe(true); - expect(o.dirty("b")).toBe(true); - expect(o.dirty("c")).toBe(true); + objectId: 'P95', + createdAt: { __type: 'Date', iso: new Date().toISOString() }, + updatedAt: { __type: 'Date', iso: new Date().toISOString() }, + }); + o.set({ a: 'a', b: 'b', c: 'c' }); + expect(o.dirty('a')).toBe(true); + expect(o.dirty('b')).toBe(true); + expect(o.dirty('c')).toBe(true); o.clear(); - expect(o.get("a")).toBe(undefined); - expect(o.get("b")).toBe(undefined); - expect(o.get("c")).toBe(undefined); + expect(o.get('a')).toBe(undefined); + expect(o.get('b')).toBe(undefined); + expect(o.get('c')).toBe(undefined); }); - it("can increment a field", () => { - const o = new ParseObject("Person"); - o.increment("age"); + it('can increment a field', () => { + const o = new ParseObject('Person'); + o.increment('age'); expect(o.attributes).toEqual({ age: 1 }); - expect(o.op("age") instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(["age"]); + 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); + 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", { amount: 4 })).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.' ); - o.set("age", 30); - o.increment("age"); + o.set('age', 30); + o.increment('age'); expect(o.attributes).toEqual({ age: 31 }); expect(o._getSaveJSON()).toEqual({ age: 31, }); - const o2 = new ParseObject("Person"); + const o2 = new ParseObject('Person'); o2._finishFetch({ - objectId: "P2", + objectId: 'P2', age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); - o2.increment("age"); + o2.increment('age'); expect(o2.attributes).toEqual({ age: 41 }); }); - it("can decrement a field", () => { - const o = new ParseObject("Person"); - o.decrement("age"); + it('can decrement a field', () => { + const o = new ParseObject('Person'); + o.decrement('age'); expect(o.attributes).toEqual({ age: -1 }); - expect(o.op("age") instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(["age"]); + 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); + 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", { amount: 4 })).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.' ); - o.set("age", 30); - o.decrement("age"); + o.set('age', 30); + o.decrement('age'); expect(o.attributes).toEqual({ age: 29 }); expect(o._getSaveJSON()).toEqual({ age: 29, }); - const o2 = new ParseObject("Person"); + const o2 = new ParseObject('Person'); o2._finishFetch({ - objectId: "ABC123", + objectId: 'ABC123', age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); - o2.decrement("age"); + o2.decrement('age'); expect(o2.attributes).toEqual({ age: 39 }); }); - it("can set nested field", () => { - const o = new ParseObject("Person"); + it('can set nested field', () => { + const o = new ParseObject('Person'); o._finishFetch({ - objectId: "setNested", + objectId: 'setNested', objectField: { number: 5, - letter: "a", + letter: 'a', }, otherField: {}, }); expect(o.attributes).toEqual({ - objectField: { number: 5, letter: "a" }, + objectField: { number: 5, letter: 'a' }, otherField: {}, }); - o.set("otherField", { hello: "world" }); - o.set("objectField.number", 20); + o.set('otherField', { hello: 'world' }); + o.set('objectField.number', 20); expect(o.attributes).toEqual({ - objectField: { number: 20, letter: "a" }, - otherField: { hello: "world" }, - }); - expect(o.op("objectField.number") instanceof SetOp).toBe(true); - expect(o.dirtyKeys()).toEqual([ - "otherField", - "objectField.number", - "objectField", - ]); + objectField: { number: 20, letter: 'a' }, + otherField: { hello: 'world' }, + }); + expect(o.op('objectField.number') instanceof SetOp).toBe(true); + expect(o.dirtyKeys()).toEqual(['otherField', 'objectField.number', 'objectField']); expect(o._getSaveJSON()).toEqual({ - "objectField.number": 20, - otherField: { hello: "world" }, + 'objectField.number': 20, + otherField: { hello: 'world' }, }); }); - it("can increment a nested field", () => { - const o = new ParseObject("Person"); + it('can increment a nested field', () => { + const o = new ParseObject('Person'); o._finishFetch({ - objectId: "incNested", + objectId: 'incNested', objectField: { number: 5, - letter: "a", + letter: 'a', }, }); expect(o.attributes).toEqual({ - objectField: { number: 5, letter: "a" }, + objectField: { number: 5, letter: 'a' }, }); - o.increment("objectField.number"); + o.increment('objectField.number'); expect(o.attributes).toEqual({ - objectField: { number: 6, letter: "a" }, + objectField: { number: 6, letter: 'a' }, }); - expect(o.op("objectField.number") instanceof IncrementOp).toBe(true); - expect(o.dirtyKeys()).toEqual(["objectField.number", "objectField"]); + expect(o.op('objectField.number') instanceof IncrementOp).toBe(true); + expect(o.dirtyKeys()).toEqual(['objectField.number', 'objectField']); expect(o._getSaveJSON()).toEqual({ - "objectField.number": { - __op: "Increment", + 'objectField.number': { + __op: 'Increment', amount: 1, }, }); // Nested objects only return values changed o._handleSaveResponse({ - objectId: "incNested", + objectId: 'incNested', objectField: { number: 6, }, }); - expect(o.get("objectField").number).toEqual(6); - expect(o.get("objectField").letter).toEqual("a"); + expect(o.get('objectField').number).toEqual(6); + expect(o.get('objectField').letter).toEqual('a'); }); - it("ignore set nested field on new object", () => { - const o = new ParseObject("Person"); - o.set("objectField.number", 20); + it('ignore set nested field on new object', () => { + const o = new ParseObject('Person'); + o.set('objectField.number', 20); expect(o.attributes).toEqual({}); - expect(o.op("objectField.number") instanceof SetOp).toBe(false); + expect(o.op('objectField.number') instanceof SetOp).toBe(false); expect(o.dirtyKeys()).toEqual([]); expect(o._getSaveJSON()).toEqual({}); }); - it("can add elements to an array field", () => { - const o = new ParseObject("Schedule"); - o.add("available", "Monday"); - o.add("available", "Wednesday"); - expect(o.get("available")).toEqual(["Monday", "Wednesday"]); + it('can add elements to an array field', () => { + const o = new ParseObject('Schedule'); + o.add('available', 'Monday'); + o.add('available', 'Wednesday'); + expect(o.get('available')).toEqual(['Monday', 'Wednesday']); - o.set("colors", ["red", "green"]); - o.add("colors", "blue"); - expect(o.get("colors")).toEqual(["red", "green", "blue"]); + o.set('colors', ['red', 'green']); + o.add('colors', 'blue'); + expect(o.get('colors')).toEqual(['red', 'green', 'blue']); o._handleSaveResponse({ - objectId: "S1", - available: ["Monday", "Wednesday"], - colors: ["red", "green", "blue"], + objectId: 'S1', + available: ['Monday', 'Wednesday'], + colors: ['red', 'green', 'blue'], }); - o.addUnique("available", "Thursday"); - o.addUnique("available", "Monday"); - expect(o.get("available")).toEqual(["Monday", "Wednesday", "Thursday"]); + o.addUnique('available', 'Thursday'); + o.addUnique('available', 'Monday'); + expect(o.get('available')).toEqual(['Monday', 'Wednesday', 'Thursday']); }); - it("can add elements to an array field in batch mode", () => { - const o = new ParseObject("Schedule"); - o.addAll("available", ["Monday", "Wednesday"]); - expect(o.get("available")).toEqual(["Monday", "Wednesday"]); + it('can add elements to an array field in batch mode', () => { + const o = new ParseObject('Schedule'); + o.addAll('available', ['Monday', 'Wednesday']); + expect(o.get('available')).toEqual(['Monday', 'Wednesday']); - o.set("colors", ["red"]); - o.addAll("colors", ["green", "blue"]); - expect(o.get("colors")).toEqual(["red", "green", "blue"]); + o.set('colors', ['red']); + o.addAll('colors', ['green', 'blue']); + expect(o.get('colors')).toEqual(['red', 'green', 'blue']); o._handleSaveResponse({ - objectId: "S1", - available: ["Monday", "Wednesday"], - colors: ["red", "green", "blue"], + objectId: 'S1', + available: ['Monday', 'Wednesday'], + colors: ['red', 'green', 'blue'], }); - o.addAllUnique("available", ["Thursday", "Monday"]); - expect(o.get("available").length).toEqual(3); + o.addAllUnique('available', ['Thursday', 'Monday']); + expect(o.get('available').length).toEqual(3); }); - it("can remove elements from an array field", () => { - const o = new ParseObject("Schedule"); - o.set("available", ["Monday", "Tuesday"]); - o.remove("available", "Tuesday"); - o.remove("available", "Saturday"); - expect(o.get("available")).toEqual(["Monday"]); + it('can remove elements from an array field', () => { + const o = new ParseObject('Schedule'); + o.set('available', ['Monday', 'Tuesday']); + o.remove('available', 'Tuesday'); + o.remove('available', 'Saturday'); + expect(o.get('available')).toEqual(['Monday']); o._handleSaveResponse({ - objectId: "S2", - available: ["Monday"], + objectId: 'S2', + available: ['Monday'], }); - o.remove("available", "Monday"); - o.remove("available", "Tuesday"); - expect(o.get("available")).toEqual([]); + o.remove('available', 'Monday'); + o.remove('available', 'Tuesday'); + expect(o.get('available')).toEqual([]); }); - it("can remove elements from an array field in batch mode", () => { - const o = new ParseObject("Schedule"); - o.set("available", ["Monday", "Tuesday"]); - o.removeAll("available", ["Tuesday", "Saturday"]); - expect(o.get("available")).toEqual(["Monday"]); + it('can remove elements from an array field in batch mode', () => { + const o = new ParseObject('Schedule'); + o.set('available', ['Monday', 'Tuesday']); + o.removeAll('available', ['Tuesday', 'Saturday']); + expect(o.get('available')).toEqual(['Monday']); o._handleSaveResponse({ - objectId: "S2", - available: ["Monday"], + objectId: 'S2', + available: ['Monday'], }); - o.removeAll("available", ["Monday", "Tuesday"]); - expect(o.get("available")).toEqual([]); + o.removeAll('available', ['Monday', 'Tuesday']); + expect(o.get('available')).toEqual([]); }); - it("can chain sets", () => { - const o = new ParseObject("Person"); - o.set("developer", true).set("platform", "web"); + it('can chain sets', () => { + const o = new ParseObject('Person'); + o.set('developer', true).set('platform', 'web'); expect(o.attributes).toEqual({ developer: true, - platform: "web", + platform: 'web', }); }); - it("can set and retrieve ACLs", () => { + it('can set and retrieve ACLs', () => { const acl = new ParseACL(); - const o = new ParseObject("Listing"); + const o = new ParseObject('Listing'); o.setACL(acl); - expect(o.get("ACL")).toBe(acl); + expect(o.get('ACL')).toBe(acl); expect(o.getACL()).toBe(acl); }); - it("can manipulate relations on fields", () => { - 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" - ); - const rel = o.relation("friends"); - expect(rel.parentClass).toBe("Person"); - expect(rel.parentId).toBe("AA"); - expect(rel.key).toBe("friends"); - const friend = new ParseObject("Person"); - friend.id = "BB"; + it('can manipulate relations on fields', () => { + 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'); + const rel = o.relation('friends'); + expect(rel.parentClass).toBe('Person'); + expect(rel.parentId).toBe('AA'); + expect(rel.key).toBe('friends'); + const friend = new ParseObject('Person'); + friend.id = 'BB'; rel.add(friend); - expect(rel.targetClassName).toBe("Person"); + expect(rel.targetClassName).toBe('Person'); }); - it("can be cloned with relation (#381)", () => { - const relationJSON = { __type: "Relation", className: "Bar" }; + it('can be cloned with relation (#381)', () => { + const relationJSON = { __type: 'Relation', className: 'Bar' }; const o = ParseObject.fromJSON({ - objectId: "7777777777", - className: "Foo", + objectId: '7777777777', + className: 'Foo', aRelation: relationJSON, }); const o2 = o.clone(); expect(o2._getSaveJSON().aRelation).toEqual(relationJSON); }); - it("can get relation from relation field", () => { - const relationJSON = { __type: "Relation", className: "Bar" }; + it('can get relation from relation field', () => { + const relationJSON = { __type: 'Relation', className: 'Bar' }; const o = ParseObject.fromJSON({ - objectId: "999", - className: "Foo", + objectId: '999', + className: 'Foo', aRelation: relationJSON, }); - const rel = o.relation("aRelation"); + const rel = o.relation('aRelation'); expect(rel.toJSON()).toEqual(relationJSON); }); - it("can detect dirty object children", () => { - const o = new ParseObject("Person"); + it('can detect dirty object children', () => { + const o = new ParseObject('Person'); o._finishFetch({ - objectId: "dirtyObj", + objectId: 'dirtyObj', obj: { a: 12 }, location: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20, longitude: 20, }, }); expect(o.dirty()).toBe(false); - o.get("obj").b = 21; - expect(o.get("obj")).toEqual({ + o.get('obj').b = 21; + expect(o.get('obj')).toEqual({ a: 12, b: 21, }); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual(["obj"]); + expect(o.dirtyKeys()).toEqual(['obj']); expect(o._getSaveJSON()).toEqual({ obj: { a: 12, b: 21, }, }); - delete o.get("obj").b; + delete o.get('obj').b; expect(o.dirty()).toBe(false); expect(o.dirtyKeys()).toEqual([]); - const loc = o.get("location"); + const loc = o.get('location'); expect(loc instanceof ParseGeoPoint).toBe(true); expect(loc.latitude).toBe(20); expect(loc.longitude).toBe(20); loc.latitude = 30; expect(loc.latitude).toBe(30); expect(o.dirty()).toBe(true); - expect(o.dirtyKeys()).toEqual(["location"]); + expect(o.dirtyKeys()).toEqual(['location']); - const p = new ParseObject("Parent"); - p.set("children", [o]); - expect(p.dirtyKeys()).toEqual(["children"]); + const p = new ParseObject('Parent'); + p.set('children', [o]); + expect(p.dirtyKeys()).toEqual(['children']); }); - it("can validate attributes", () => { - const o = new ParseObject("Listing"); + it('can validate attributes', () => { + const o = new ParseObject('Listing'); expect( o.validate({ - ACL: "not an acl", + ACL: 'not an acl', }) - ).toEqual( - new ParseError(ParseError.OTHER_CAUSE, "ACL must be a Parse ACL.") - ); + ).toEqual(new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.')); expect( o.validate({ - "invalid!key": 12, + 'invalid!key': 12, }) ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME)); expect( o.validate({ - noProblem: "here", + noProblem: 'here', }) ).toBe(false); expect( o.validate({ - "dot.field": "here", + 'dot.field': 'here', }) ).toBe(false); }); - it("validates attributes on set()", () => { - const o = new ParseObject("Listing"); - expect(o.set("ACL", "not an acl")).toBe(false); - expect(o.set("ACL", { "*": { read: true, write: false } })).toBe(o); - expect(o.set("$$$", "o_O")).toBe(false); + it('validates attributes on set()', () => { + const o = new ParseObject('Listing'); + expect(o.set('ACL', 'not an acl')).toBe(false); + expect(o.set('ACL', { '*': { read: true, write: false } })).toBe(o); + expect(o.set('$$$', 'o_O')).toBe(false); - o.set("$$$", "o_O", { + o.set('$$$', 'o_O', { error: function (obj, err) { expect(obj).toBe(o); expect(err.code).toBe(105); @@ -913,194 +891,194 @@ describe("ParseObject", () => { }); }); - it("ignores validation if ignoreValidation option is passed to set()", () => { - const o = new ParseObject("Listing"); - expect(o.set("$$$", "o_O", { ignoreValidation: true })).toBe(o); + it('ignores validation if ignoreValidation option is passed to set()', () => { + const o = new ParseObject('Listing'); + expect(o.set('$$$', 'o_O', { ignoreValidation: true })).toBe(o); }); - it("can test object validity", () => { + it('can test object validity', () => { // Note: an object should never become invalid through normal use, but // it's possible that someone could manipulate it to become invalid - const o = new ParseObject("Item"); + const o = new ParseObject('Item'); expect(o.isValid()).toBe(true); - o.set("someKey", "someValue"); + o.set('someKey', 'someValue'); expect(o.isValid()).toBe(true); o._finishFetch({ - objectId: "O3", - "invalid!key": "oops", + objectId: 'O3', + 'invalid!key': 'oops', }); expect(o.isValid()).toBe(false); }); - it("shares data among different instances of an object", () => { - const o = new ParseObject("Person"); - o.id = "P2"; - const o2 = new ParseObject("Person"); - o2.id = "P2"; - o.set("age", 22); - expect(o.get("age")).toBe(22); - expect(o2.get("age")).toBe(22); + it('shares data among different instances of an object', () => { + const o = new ParseObject('Person'); + o.id = 'P2'; + const o2 = new ParseObject('Person'); + o2.id = 'P2'; + o.set('age', 22); + expect(o.get('age')).toBe(22); + expect(o2.get('age')).toBe(22); }); - it("does not stack-overflow when encoding recursive pointers", () => { + it('does not stack-overflow when encoding recursive pointers', () => { const o = ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "recurParent", + __type: 'Object', + className: 'Item', + objectId: 'recurParent', child: { - __type: "Pointer", - className: "Item", - objectId: "recurChild", + __type: 'Pointer', + className: 'Item', + objectId: 'recurChild', }, }); expect(o.toJSON()).toEqual({ - objectId: "recurParent", + objectId: 'recurParent', child: { - __type: "Pointer", - className: "Item", - objectId: "recurChild", + __type: 'Pointer', + className: 'Item', + objectId: 'recurChild', }, }); ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "recurChild", + __type: 'Object', + className: 'Item', + objectId: 'recurChild', parent: { - __type: "Pointer", - className: "Item", - objectId: "recurParent", + __type: 'Pointer', + className: 'Item', + objectId: 'recurParent', }, }); expect(o.toJSON()).toEqual({ - objectId: "recurParent", + objectId: 'recurParent', child: { - __type: "Object", - className: "Item", - objectId: "recurChild", + __type: 'Object', + className: 'Item', + objectId: 'recurChild', parent: { - __type: "Pointer", - className: "Item", - objectId: "recurParent", + __type: 'Pointer', + className: 'Item', + objectId: 'recurParent', }, }, }); }); - it("properly encodes createdAt/updatedAt dates on nested objects", () => { + it('properly encodes createdAt/updatedAt dates on nested objects', () => { const o = ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "recurParent", - createdAt: "1970-01-01T00:00:00.000Z", - updatedAt: "1970-01-01T00:00:00.000Z", + __type: 'Object', + className: 'Item', + objectId: 'recurParent', + createdAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z', aDate: { - __type: "Date", - iso: "1970-01-01T00:00:00.000Z", + __type: 'Date', + iso: '1970-01-01T00:00:00.000Z', }, child: { - __type: "Pointer", - className: "Item", - objectId: "recurChild", + __type: 'Pointer', + className: 'Item', + objectId: 'recurChild', }, }); expect(o.createdAt.getTime()).toBe(new Date(0).getTime()); expect(o.updatedAt.getTime()).toBe(new Date(0).getTime()); - expect(o.get("aDate").getTime()).toBe(new Date(0).getTime()); + expect(o.get('aDate').getTime()).toBe(new Date(0).getTime()); ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "recurChild", - createdAt: "1970-01-01T00:00:00.000Z", - updatedAt: "1970-01-01T00:00:00.000Z", + __type: 'Object', + className: 'Item', + objectId: 'recurChild', + createdAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z', parent: { - __type: "Pointer", - className: "Item", - objectId: "recurParent", + __type: 'Pointer', + className: 'Item', + objectId: 'recurParent', }, }); expect(o.toJSON()).toEqual({ - objectId: "recurParent", - createdAt: "1970-01-01T00:00:00.000Z", - updatedAt: "1970-01-01T00:00:00.000Z", + objectId: 'recurParent', + createdAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z', aDate: { - __type: "Date", - iso: "1970-01-01T00:00:00.000Z", + __type: 'Date', + iso: '1970-01-01T00:00:00.000Z', }, child: { - __type: "Object", - className: "Item", - objectId: "recurChild", - createdAt: "1970-01-01T00:00:00.000Z", - updatedAt: "1970-01-01T00:00:00.000Z", + __type: 'Object', + className: 'Item', + objectId: 'recurChild', + createdAt: '1970-01-01T00:00:00.000Z', + updatedAt: '1970-01-01T00:00:00.000Z', parent: { - __type: "Pointer", - className: "Item", - objectId: "recurParent", + __type: 'Pointer', + className: 'Item', + objectId: 'recurParent', }, }, }); }); - it("encodes multiple layers of nested objects", () => { + it('encodes multiple layers of nested objects', () => { const grandparent = ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "nestedGrand", + __type: 'Object', + className: 'Item', + objectId: 'nestedGrand', child: { - __type: "Pointer", - className: "Item", - objectId: "nestedParent", + __type: 'Pointer', + className: 'Item', + objectId: 'nestedParent', }, }); const parent = ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "nestedParent", + __type: 'Object', + className: 'Item', + objectId: 'nestedParent', child: { - __type: "Pointer", - className: "Item", - objectId: "nestedChild", + __type: 'Pointer', + className: 'Item', + objectId: 'nestedChild', }, }); const child = ParseObject.fromJSON({ - __type: "Object", - className: "Item", - objectId: "nestedChild", + __type: 'Object', + className: 'Item', + objectId: 'nestedChild', count: 12, }); - expect(grandparent.get("child").id).toBe(parent.id); - expect(grandparent.get("child").get("child").id).toBe(child.id); + expect(grandparent.get('child').id).toBe(parent.id); + expect(grandparent.get('child').get('child').id).toBe(child.id); expect(grandparent.toJSON()).toEqual({ - objectId: "nestedGrand", + objectId: 'nestedGrand', child: { - __type: "Object", - className: "Item", - objectId: "nestedParent", + __type: 'Object', + className: 'Item', + objectId: 'nestedParent', child: { - __type: "Object", - className: "Item", - objectId: "nestedChild", + __type: 'Object', + className: 'Item', + objectId: 'nestedChild', count: 12, }, }, }); }); - it("updates the existed flag when saved", () => { - const o = new ParseObject("Item"); + it('updates the existed flag when saved', () => { + const o = new ParseObject('Item'); expect(o.existed()).toBe(false); expect(o.isNew()).toBe(true); o._handleSaveResponse( { - objectId: "I2", + objectId: 'I2', }, 201 ); @@ -1109,32 +1087,32 @@ describe("ParseObject", () => { expect(o.existed()).toBe(true); }); - it("check existed without object state", () => { - const o = new ParseObject("Item"); - o.id = "test890"; + it('check existed without object state', () => { + const o = new ParseObject('Item'); + o.id = 'test890'; expect(o.existed()).toBe(false); }); - it("commits changes to server data when saved", () => { - const p = new ParseObject("Person"); - p.id = "P3"; - p.set("age", 24); + it('commits changes to server data when saved', () => { + const p = new ParseObject('Person'); + p.id = 'P3'; + p.set('age', 24); expect(p._getServerData()).toEqual({}); - expect(p.op("age") instanceof SetOp).toBe(true); + 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, }); - expect(p.op("age")).toBe(undefined); + expect(p.op('age')).toBe(undefined); }); - it("handle GeoPoint changes for server", () => { - const p = new ParseObject("Person"); - p.id = "PPoint"; + it('handle GeoPoint changes for server', () => { + const p = new ParseObject('Person'); + p.id = 'PPoint'; const created = new Date(); const geopoint = new ParseGeoPoint(0, 0); p._handleSaveResponse({ @@ -1149,9 +1127,9 @@ describe("ParseObject", () => { expect(p._getServerData().point instanceof ParseGeoPoint).toBe(true); }); - it("handle Polygon changes for server", () => { - const p = new ParseObject("Person"); - p.id = "PPolygon"; + it('handle Polygon changes for server', () => { + const p = new ParseObject('Person'); + p.id = 'PPolygon'; const created = new Date(); const polygon = new ParsePolygon([ [0, 0], @@ -1172,9 +1150,9 @@ describe("ParseObject", () => { expect(p._getServerData().shape instanceof ParsePolygon).toBe(true); }); - it("handle createdAt string for server", () => { - const p = new ParseObject("Person"); - p.id = "P9"; + it('handle createdAt string for server', () => { + const p = new ParseObject('Person'); + p.id = 'P9'; const created = new Date(); p._handleSaveResponse({ createdAt: created.toISOString(), @@ -1185,20 +1163,20 @@ describe("ParseObject", () => { }); }); - it("isDataAvailable", () => { - const p = new ParseObject("Person"); - p.id = "isdataavailable"; - p.set("age", 24); + it('isDataAvailable', () => { + const p = new ParseObject('Person'); + p.id = 'isdataavailable'; + p.set('age', 24); 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); }); - it("handles ACL when saved", () => { - const p = new ParseObject("Person"); + it('handles ACL when saved', () => { + const p = new ParseObject('Person'); p._handleSaveResponse( { @@ -1212,113 +1190,112 @@ describe("ParseObject", () => { expect(acl instanceof ParseACL).toBe(true); }); - it("replaces a local id with a real one when saved", () => { - const p = new ParseObject("Person"); - p.set("age", 34); + it('replaces a local id with a real one when saved', () => { + const p = new ParseObject('Person'); + p.set('age', 34); expect(p._localId).toBeTruthy(); expect(p.id).toBe(undefined); const oldState = SingleInstanceStateController.getState({ - className: "Person", + className: 'Person', id: p._localId, }); p._handleSaveResponse({ - objectId: "P4", + objectId: 'P4', }); expect(p._localId).toBe(undefined); - expect(p.id).toBe("P4"); + expect(p.id).toBe('P4'); const newState = SingleInstanceStateController.getState({ - className: "Person", - id: "P4", + className: 'Person', + id: 'P4', }); expect(oldState.serverData).toBe(newState.serverData); expect(oldState.pendingOps).toBe(newState.pendingOps); expect(oldState.tasks).toBe(newState.tasks); }); - it("marks inflated objects as existed", () => { + it('marks inflated objects as existed', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "iexist", + className: 'Item', + objectId: 'iexist', count: 7, }); expect(o.existed()).toBe(true); }); - it("can revert unsaved ops", () => { + it('can revert unsaved ops', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "canrevert", + className: 'Item', + objectId: 'canrevert', count: 5, }); o.set({ cool: true }); - o.increment("count"); - expect(o.get("cool")).toBe(true); - expect(o.get("count")).toBe(6); + o.increment('count'); + expect(o.get('cool')).toBe(true); + expect(o.get('count')).toBe(6); o.revert(); - expect(o.get("cool")).toBe(undefined); - expect(o.op("cool")).toBe(undefined); - expect(o.get("count")).toBe(5); - expect(o.op("count")).toBe(undefined); + expect(o.get('cool')).toBe(undefined); + expect(o.op('cool')).toBe(undefined); + expect(o.get('count')).toBe(5); + expect(o.op('count')).toBe(undefined); }); - it("can revert a specific field in unsaved ops", () => { + it('can revert a specific field in unsaved ops', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "canrevertspecific", + className: 'Item', + objectId: 'canrevertspecific', count: 5, }); o.set({ cool: true }); - o.increment("count"); - expect(o.get("cool")).toBe(true); - expect(o.get("count")).toBe(6); - o.revert("cool"); - expect(o.get("cool")).toBe(undefined); - expect(o.op("cool")).toBe(undefined); - expect(o.get("count")).toBe(6); - expect(o.op("count")).not.toBe(undefined); + o.increment('count'); + expect(o.get('cool')).toBe(true); + expect(o.get('count')).toBe(6); + o.revert('cool'); + expect(o.get('cool')).toBe(undefined); + expect(o.op('cool')).toBe(undefined); + expect(o.get('count')).toBe(6); + expect(o.op('count')).not.toBe(undefined); }); - it("can revert multiple fields in unsaved ops", () => { + it('can revert multiple fields in unsaved ops', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "canrevertmultiple", + className: 'Item', + objectId: 'canrevertmultiple', count: 5, age: 18, - gender: "female", - }); - o.set({ cool: true, gender: "male" }); - o.increment("count"); - o.increment("age"); - expect(o.get("cool")).toBe(true); - expect(o.get("count")).toBe(6); - expect(o.get("age")).toBe(19); - expect(o.get("gender")).toBe("male"); - o.revert("age", "count", "gender"); - expect(o.get("cool")).toBe(true); - expect(o.op("cool")).not.toBe(undefined); - expect(o.get("count")).toBe(5); - expect(o.op("count")).toBe(undefined); - expect(o.get("age")).toBe(18); - expect(o.op("age")).toBe(undefined); - expect(o.get("gender")).toBe("female"); - expect(o.op("gender")).toBe(undefined); - }); - - it("throws if an array is provided", () => { + gender: 'female', + }); + o.set({ cool: true, gender: 'male' }); + o.increment('count'); + o.increment('age'); + expect(o.get('cool')).toBe(true); + expect(o.get('count')).toBe(6); + expect(o.get('age')).toBe(19); + expect(o.get('gender')).toBe('male'); + o.revert('age', 'count', 'gender'); + expect(o.get('cool')).toBe(true); + expect(o.op('cool')).not.toBe(undefined); + expect(o.get('count')).toBe(5); + expect(o.op('count')).toBe(undefined); + expect(o.get('age')).toBe(18); + expect(o.op('age')).toBe(undefined); + expect(o.get('gender')).toBe('female'); + expect(o.op('gender')).toBe(undefined); + }); + + it('throws if an array is provided', () => { const o = ParseObject.fromJSON({ - className: "Item", - objectId: "throwforarray", + className: 'Item', + objectId: 'throwforarray', count: 5, age: 18, - gender: "female", + gender: 'female', }); - o.set({ cool: true, gender: "male" }); + 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"]); + o.revert(['age']); }).toThrow(err); expect(function () { @@ -1326,47 +1303,39 @@ describe("ParseObject", () => { }).toThrow(err); expect(function () { - o.revert("gender", ["age"]); + o.revert('gender', ['age']); }).toThrow(err); }); - it("can fetchWithInclude", async () => { + it('can fetchWithInclude', async () => { const objectController = CoreManager.getObjectController(); const spy = jest - .spyOn(objectController, "fetch") + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); - const parent = new ParseObject("Person"); - await parent.fetchWithInclude("child", { + const parent = new ParseObject('Person'); + await parent.fetchWithInclude('child', { useMasterKey: true, - sessionToken: "123", + sessionToken: '123', }); - await parent.fetchWithInclude(["child"]); - await parent.fetchWithInclude([["child"]]); + 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"] }, + { 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 () => { + it('fetchAll with empty values', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -1376,14 +1345,14 @@ describe("ParseObject", () => { ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); const results = await ParseObject.fetchAll([]); expect(results).toEqual([]); expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it("fetchAll with null", async () => { + it('fetchAll with null', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -1393,158 +1362,142 @@ describe("ParseObject", () => { ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); const results = await ParseObject.fetchAll(null); expect(results).toEqual(undefined); expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it("fetchAll unique instance", async () => { + it('fetchAll unique instance', async () => { ParseObject.disableSingleInstance(); - const obj = new ParseObject("Item"); - obj.id = "fetch0"; + const obj = new ParseObject('Item'); + obj.id = 'fetch0'; const results = await ParseObject.fetchAll([obj]); expect(results[0].id).toEqual(obj.id); }); - it("fetchAll objects does not exist on server", async () => { - jest.spyOn(mockQuery.prototype, "find").mockImplementationOnce(() => { + it('fetchAll objects does not exist on server', async () => { + jest.spyOn(mockQuery.prototype, 'find').mockImplementationOnce(() => { return Promise.resolve([]); }); - const obj = new ParseObject("Item"); - obj.id = "fetch-1"; + const obj = new ParseObject('Item'); + obj.id = 'fetch-1'; try { await ParseObject.fetchAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("All objects must exist on the server."); + expect(e.message).toBe('All objects must exist on the server.'); } }); - it("fetchAll unsaved objects", async () => { - const obj = new ParseObject("Item"); + it('fetchAll unsaved objects', async () => { + const obj = new ParseObject('Item'); try { await ParseObject.fetchAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("All objects must have an ID"); + expect(e.message).toBe('All objects must have an ID'); } }); - it("fetchAll objects with different classes", async () => { - const obj = new ParseObject("Item"); - const obj2 = new ParseObject("TestObject"); + it('fetchAll objects with different classes', async () => { + const obj = new ParseObject('Item'); + const obj2 = new ParseObject('TestObject'); try { await ParseObject.fetchAll([obj, obj2]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("All objects must have an ID"); + expect(e.message).toBe('All objects must have an ID'); } }); - it("fetchAll saved objects with different classes", async () => { - const obj1 = new ParseObject("Item"); - const obj2 = new ParseObject("TestObject"); - obj1.id = "fetch1"; - obj2.id = "fetch2"; + it('fetchAll saved objects with different classes', async () => { + const obj1 = new ParseObject('Item'); + const obj2 = new ParseObject('TestObject'); + obj1.id = 'fetch1'; + obj2.id = 'fetch2'; try { await ParseObject.fetchAll([obj1, obj2]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("All objects should be of the same class"); + expect(e.message).toBe('All objects should be of the same class'); } }); - it("can fetchAllWithInclude", async () => { + it('can fetchAllWithInclude', async () => { const objectController = CoreManager.getObjectController(); const spy = jest - .spyOn(objectController, "fetch") + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); - const parent = new ParseObject("Person"); - await ParseObject.fetchAllWithInclude([parent], "child", { + const parent = new ParseObject('Person'); + await ParseObject.fetchAllWithInclude([parent], 'child', { useMasterKey: true, - sessionToken: "123", + sessionToken: '123', }); - await ParseObject.fetchAllWithInclude([parent], ["child"]); - await ParseObject.fetchAllWithInclude([parent], [["child"]]); + 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"] }, + { 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 () => { + it('can fetchAllIfNeededWithInclude', async () => { const objectController = CoreManager.getObjectController(); const spy = jest - .spyOn(objectController, "fetch") + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); - const parent = new ParseObject("Person"); - await ParseObject.fetchAllIfNeededWithInclude([parent], "child", { + const parent = new ParseObject('Person'); + await ParseObject.fetchAllIfNeededWithInclude([parent], 'child', { useMasterKey: true, - sessionToken: "123", + sessionToken: '123', }); - await ParseObject.fetchAllIfNeededWithInclude([parent], ["child"]); - await ParseObject.fetchAllIfNeededWithInclude([parent], [["child"]]); + 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"] }, + { 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(); }); - it("can check if object exists", async () => { - const parent = new ParseObject("Person"); + 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(() => { + jest.spyOn(mockQuery.prototype, 'get').mockImplementationOnce(() => { return Promise.reject({ code: 101, }); }); expect(await parent.exists()).toBe(false); - jest.spyOn(mockQuery.prototype, "get").mockImplementationOnce(() => { + jest.spyOn(mockQuery.prototype, 'get').mockImplementationOnce(() => { return Promise.reject({ code: 1, - message: "Internal Server Error", + message: 'Internal Server Error', }); }); try { @@ -1555,116 +1508,116 @@ describe("ParseObject", () => { } }); - it("can save the object", (done) => { + it('can save the object', done => { CoreManager.getRESTController()._setXHR( mockXHR([ { status: 200, response: { - objectId: "P5", + objectId: 'P5', count: 1, }, }, ]) ); - const p = new ParseObject("Person"); - p.set("age", 38); - p.increment("count"); - p.save().then((obj) => { + const p = new ParseObject('Person'); + p.set('age', 38); + p.increment('count'); + p.save().then(obj => { expect(obj).toBe(p); - expect(obj.get("age")).toBe(38); - expect(obj.get("count")).toBe(1); - expect(obj.op("age")).toBe(undefined); + expect(obj.get('age')).toBe(38); + expect(obj.get('count')).toBe(1); + expect(obj.op('age')).toBe(undefined); expect(obj.dirty()).toBe(false); done(); }); }); - 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", + objectId: 'P8', }, }, ]) ); - const p = new ParseObject("Person"); - p.save("foo", "bar").then((obj) => { + const p = new ParseObject('Person'); + p.save('foo', 'bar').then(obj => { expect(obj).toBe(p); - expect(obj.get("foo")).toBe("bar"); + 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" }, + response: { objectId: 'newattributes' }, }, ]) ); - let o = new ParseObject("Item"); - o.save({ key: "value" }) + let o = new ParseObject('Item'); + o.save({ key: 'value' }) .then(() => { - expect(o.get("key")).toBe("value"); + expect(o.get('key')).toBe('value'); - o = new ParseObject("Item"); - return o.save({ ACL: "not an acl" }); + o = new ParseObject('Item'); + return o.save({ ACL: 'not an acl' }); }) - .then(null, (error) => { + .then(null, error => { expect(error.code).toBe(-1); done(); }); }); - it("accepts context on save", async () => { + it('accepts context on save', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ { status: 200, - response: { objectId: "newattributes" }, + response: { objectId: 'newattributes' }, }, ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); // Save object - const context = { a: "a" }; - const obj = new ParseObject("Item"); + const context = { a: 'a' }; + const obj = new ParseObject('Item'); 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" }, + objectId: 'newattributes', + deletedKey: { __op: 'Delete' }, }, }, ]) ); - const o = new ParseObject("Item"); - o.save({ key: "value", deletedKey: "keyToDelete" }).then(() => { - expect(o.get("key")).toBe("value"); - expect(o.get("deletedKey")).toBeUndefined(); + const o = new ParseObject('Item'); + o.save({ key: 'value', deletedKey: 'keyToDelete' }).then(() => { + expect(o.get('key')).toBe('value'); + expect(o.get('deletedKey')).toBeUndefined(); done(); }); }); - it("can make changes while in the process of a save", async () => { + it('can make changes while in the process of a save', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -1673,27 +1626,27 @@ describe("ParseObject", () => { RESTController._setXHR(function () { return xhr; }); - const p = new ParseObject("Person"); - p.set("age", 38); + const p = new ParseObject('Person'); + p.set('age', 38); const result = p.save().then(() => { expect(p._getServerData()).toEqual({ age: 38 }); expect(p._getPendingOps().length).toBe(1); - expect(p.get("age")).toBe(39); + expect(p.get('age')).toBe(39); }); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); - p.increment("age"); - expect(p.get("age")).toBe(39); + p.increment('age'); + expect(p.get('age')).toBe(39); xhr.status = 200; - xhr.responseText = JSON.stringify({ objectId: "P12" }); + xhr.responseText = JSON.stringify({ objectId: 'P12' }); xhr.readyState = 4; xhr.onreadystatechange(); await result; }); - it("will queue save operations", async () => { + it('will queue save operations', async () => { const xhrs = []; RESTController._setXHR(function () { const xhr = { @@ -1704,16 +1657,16 @@ describe("ParseObject", () => { xhrs.push(xhr); return xhr; }); - const p = new ParseObject("Person"); + const p = new ParseObject('Person'); expect(p._getPendingOps().length).toBe(1); expect(xhrs.length).toBe(0); - p.increment("updates"); + p.increment('updates'); p.save(); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); expect(xhrs.length).toBe(1); - p.increment("updates"); + p.increment('updates'); p.save(); jest.runAllTicks(); await flushPromises(); @@ -1721,19 +1674,19 @@ describe("ParseObject", () => { expect(xhrs.length).toBe(1); xhrs[0].status = 200; - xhrs[0].responseText = JSON.stringify({ objectId: "P15", updates: 1 }); + xhrs[0].responseText = JSON.stringify({ objectId: 'P15', updates: 1 }); xhrs[0].readyState = 4; xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); expect(p._getServerData()).toEqual({ updates: 1 }); - expect(p.get("updates")).toBe(2); + expect(p.get('updates')).toBe(2); expect(p._getPendingOps().length).toBe(2); expect(xhrs.length).toBe(2); }); - it("will leave the pending ops queue untouched when a lone save fails", async () => { + it('will leave the pending ops queue untouched when a lone save fails', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -1742,15 +1695,15 @@ describe("ParseObject", () => { RESTController._setXHR(function () { return xhr; }); - const p = new ParseObject("Per$on"); + const p = new ParseObject('Per$on'); expect(p._getPendingOps().length).toBe(1); - p.increment("updates"); - const result = p.save().then(null, (err) => { + p.increment('updates'); + const result = p.save().then(null, err => { expect(err.code).toBe(103); - expect(err.message).toBe("Invalid class name"); + expect(err.message).toBe('Invalid class name'); expect(p._getPendingOps().length).toBe(1); - expect(p.dirtyKeys()).toEqual(["updates"]); - expect(p.get("updates")).toBe(1); + expect(p.dirtyKeys()).toEqual(['updates']); + expect(p.get('updates')).toBe(1); }); jest.runAllTicks(); await flushPromises(); @@ -1758,14 +1711,14 @@ describe("ParseObject", () => { xhr.status = 404; xhr.responseText = JSON.stringify({ code: 103, - error: "Invalid class name", + error: 'Invalid class name', }); xhr.readyState = 4; xhr.onreadystatechange(); await result; }); - it("will merge pending Ops when a save fails and others are pending", async () => { + it('will merge pending Ops when a save fails and others are pending', async () => { const xhrs = []; RESTController._setXHR(function () { const xhr = { @@ -1776,14 +1729,14 @@ describe("ParseObject", () => { xhrs.push(xhr); return xhr; }); - const p = new ParseObject("Per$on"); + const p = new ParseObject('Per$on'); expect(p._getPendingOps().length).toBe(1); - p.increment("updates"); + p.increment('updates'); p.save().catch(() => {}); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); - p.set("updates", 12); + p.set('updates', 12); p.save().catch(() => {}); jest.runAllTicks(); await flushPromises(); @@ -1793,7 +1746,7 @@ describe("ParseObject", () => { xhrs[0].status = 404; xhrs[0].responseText = JSON.stringify({ code: 103, - error: "Invalid class name", + error: 'Invalid class name', }); xhrs[0].readyState = 4; xhrs[0].onreadystatechange(); @@ -1805,7 +1758,7 @@ describe("ParseObject", () => { }); }); - it("will deep-save the children of an object", async () => { + it('will deep-save the children of an object', async () => { const xhrs = []; RESTController._setXHR(function () { const xhr = { @@ -1818,69 +1771,61 @@ describe("ParseObject", () => { xhrs.push(xhr); return xhr; }); - const parent = new ParseObject("Item"); - const child = new ParseObject("Item"); - child.set("value", 5); - parent.set("child", child); + const parent = new ParseObject('Item'); + const child = new ParseObject('Item'); + child.set('value', 5); + parent.set('child', child); const result = parent.save().then(() => { - expect(child.id).toBe("child"); + expect(child.id).toBe('child'); expect(child.dirty()).toBe(false); - expect(parent.id).toBe("parent"); + expect(parent.id).toBe('parent'); }); jest.runAllTicks(); 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(); expect(xhrs.length).toBe(2); - xhrs[1].responseText = JSON.stringify({ objectId: "parent" }); + xhrs[1].responseText = JSON.stringify({ objectId: 'parent' }); xhrs[1].onreadystatechange(); jest.runAllTicks(); await result; }); - it("will fail for a circular dependency of non-existing objects", () => { - const parent = new ParseObject("Item"); - 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." - ); + it('will fail for a circular dependency of non-existing objects', () => { + const parent = new ParseObject('Item'); + 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.'); }); - it("will fail for deeper unsaved objects", () => { - const parent = new ParseObject("Item"); - const child = new ParseObject("Item"); - const grandchild = new ParseObject("Item"); - parent.set("child", child); - child.set("child", grandchild); + it('will fail for deeper unsaved objects', () => { + const parent = new ParseObject('Item'); + const child = new ParseObject('Item'); + const grandchild = new ParseObject('Item'); + 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", () => { - const post = new ParseObject("Post"); - post.id = "141414"; + it('does not mark shallow objects as dirty', () => { + const post = new ParseObject('Post'); + post.id = '141414'; expect(post.dirty()).toBe(false); - const comment = new ParseObject("Comment"); - comment.set("parent", post); + const comment = new ParseObject('Comment'); + comment.set('parent', post); expect(unsavedChildren(comment)).toEqual([]); }); - it("can fetch an object given an id", async () => { + it('can fetch an object given an id', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -1891,15 +1836,15 @@ describe("ParseObject", () => { }, ]) ); - const p = new ParseObject("Person"); - p.id = "P55"; - await p.fetch().then((res) => { + const p = new ParseObject('Person'); + p.id = 'P55'; + await p.fetch().then(res => { expect(p).toBe(res); expect(p.attributes).toEqual({ count: 10 }); }); }); - it("throw for fetch with empty string as ID", async () => { + it('throw for fetch with empty string as ID', async () => { expect.assertions(1); CoreManager.getRESTController()._setXHR( mockXHR([ @@ -1911,40 +1856,40 @@ describe("ParseObject", () => { }, ]) ); - const p = new ParseObject("Person"); - p.id = ""; + 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") + new ParseError(ParseError.MISSING_OBJECT_ID, 'Object does not have an ID') ); }); - it("should fail saveAll batch cycle", async () => { - const obj = new ParseObject("Item"); - obj.set("child", obj); + it('should fail saveAll batch cycle', async () => { + const obj = new ParseObject('Item'); + obj.set('child', obj); try { await ParseObject.saveAll([obj]); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("Tried to save a batch with a cycle."); + expect(e.message).toBe('Tried to save a batch with a cycle.'); } }); - it("should fail on invalid date", (done) => { - const obj = new ParseObject("Item"); - obj.set("when", new Date(Date.parse(null))); + 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"); + done.fail('Expected invalid date to fail'); }) - .catch((error) => { + .catch(error => { expect(error[0].code).toEqual(ParseError.INCORRECT_TYPE); - expect(error[0].message).toEqual("Tried to encode an invalid date."); + 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 () => { + it('can save a ring of objects, given one exists', async () => { const xhrs = []; RESTController._setXHR(function () { const xhr = { @@ -1957,46 +1902,40 @@ describe("ParseObject", () => { xhrs.push(xhr); return xhr; }); - const parent = new ParseObject("Item"); - const child = new ParseObject("Item"); - child.id = "child"; - parent.set("child", child); - child.set("parent", parent); + const parent = new ParseObject('Item'); + const child = new ParseObject('Item'); + child.id = 'child'; + parent.set('child', child); + child.set('parent', parent); const result = ParseObject.saveAll([parent, child]).then(() => { expect(child.dirty()).toBe(false); - expect(parent.id).toBe("parent"); + expect(parent.id).toBe('parent'); }); jest.runAllTicks(); await flushPromises(); expect(xhrs.length).toBe(1); - expect(xhrs[0].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(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ { - method: "POST", - path: "/1/classes/Item", + method: 'POST', + path: '/1/classes/Item', body: { child: { - __type: "Pointer", - className: "Item", - objectId: "child", + __type: 'Pointer', + className: 'Item', + objectId: 'child', }, }, }, ]); - xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "parent" } }, - ]); + xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'parent' } }]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); - expect(parent.id).toBe("parent"); + expect(parent.id).toBe('parent'); expect(xhrs.length).toBe(2); xhrs[1].responseText = JSON.stringify([{ success: {} }]); @@ -2006,7 +1945,7 @@ describe("ParseObject", () => { await result; }); - it("accepts context on saveAll", async () => { + it('accepts context on saveAll', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ @@ -2018,19 +1957,19 @@ describe("ParseObject", () => { ); // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); // Save object - const context = { a: "saveAll" }; - const obj = new ParseObject("Item"); - obj.id = "pid"; - obj.set("test", "value"); + const context = { a: 'saveAll' }; + const obj = new ParseObject('Item'); + obj.id = 'pid'; + obj.set('test', 'value'); await ParseObject.saveAll([obj], { context, useMasterKey: true }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it("accepts context on destroyAll", async () => { + it('accepts context on destroyAll', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ @@ -2042,18 +1981,18 @@ describe("ParseObject", () => { ); // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); // Save object - const context = { a: "b" }; - const obj = new ParseObject("Item"); - obj.id = "pid"; + const context = { a: 'b' }; + const obj = new ParseObject('Item'); + obj.id = 'pid'; await ParseObject.destroyAll([obj], { context: context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it("destroyAll with options", async () => { + it('destroyAll with options', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ @@ -2064,22 +2003,22 @@ describe("ParseObject", () => { ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); - const obj = new ParseObject("Item"); - obj.id = "pid"; + const obj = new ParseObject('Item'); + obj.id = 'pid'; await ParseObject.destroyAll([obj], { useMasterKey: true, - sessionToken: "r:1234", + sessionToken: 'r:1234', batchSize: 25, }); const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); - expect(jsonBody._MasterKey).toBe("C"); - expect(jsonBody._SessionToken).toBe("r:1234"); + expect(jsonBody._MasterKey).toBe('C'); + expect(jsonBody._SessionToken).toBe('r:1234'); }); - it("destroyAll with empty values", async () => { + it('destroyAll with empty values', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -2089,7 +2028,7 @@ describe("ParseObject", () => { ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); let results = await ParseObject.destroyAll([]); expect(results).toEqual([]); @@ -2099,7 +2038,7 @@ describe("ParseObject", () => { expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it("destroyAll unsaved objects", async () => { + it('destroyAll unsaved objects', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -2109,15 +2048,15 @@ describe("ParseObject", () => { ]) ); const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + 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); }); - it("destroyAll handle error response", async () => { + it('destroyAll handle error response', async () => { CoreManager.getRESTController()._setXHR( mockXHR([ { @@ -2126,7 +2065,7 @@ describe("ParseObject", () => { { error: { code: 101, - error: "Object not found", + error: 'Object not found', }, }, ], @@ -2134,8 +2073,8 @@ describe("ParseObject", () => { ]) ); - const obj = new ParseObject("Item"); - obj.id = "toDelete1"; + const obj = new ParseObject('Item'); + obj.id = 'toDelete1'; try { await ParseObject.destroyAll([obj]); expect(true).toBe(false); @@ -2144,7 +2083,7 @@ describe("ParseObject", () => { } }); - it("can save a chain of unsaved objects", async () => { + it('can save a chain of unsaved objects', async () => { const xhrs = []; RESTController._setXHR(function () { const xhr = { @@ -2157,94 +2096,78 @@ describe("ParseObject", () => { xhrs.push(xhr); return xhr; }); - const parent = new ParseObject("Item"); - const child = new ParseObject("Item"); - const grandchild = new ParseObject("Item"); - parent.set("child", child); - child.set("child", grandchild); + const parent = new ParseObject('Item'); + const child = new ParseObject('Item'); + const grandchild = new ParseObject('Item'); + parent.set('child', child); + child.set('child', grandchild); const result = ParseObject.saveAll([parent]).then(() => { expect(child.dirty()).toBe(false); expect(grandchild.dirty()).toBe(false); - expect(parent.id).toBe("parent"); - expect(child.id).toBe("child"); - expect(grandchild.id).toBe("grandchild"); + expect(parent.id).toBe('parent'); + expect(child.id).toBe('child'); + expect(grandchild.id).toBe('grandchild'); }); jest.runAllTicks(); await flushPromises(); expect(xhrs.length).toBe(1); - expect(xhrs[0].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(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ { - method: "POST", - path: "/1/classes/Item", + method: 'POST', + path: '/1/classes/Item', body: {}, }, ]); - xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "grandchild" } }, - ]); + 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(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", + method: 'POST', + path: '/1/classes/Item', body: { child: { - __type: "Pointer", - className: "Item", - objectId: "grandchild", + __type: 'Pointer', + className: 'Item', + objectId: 'grandchild', }, }, }, ]); - xhrs[1].responseText = JSON.stringify([{ success: { objectId: "child" } }]); + 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(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", + method: 'POST', + path: '/1/classes/Item', body: { child: { - __type: "Pointer", - className: "Item", - objectId: "child", + __type: 'Pointer', + className: 'Item', + objectId: 'child', }, }, }, ]); - xhrs[2].responseText = JSON.stringify([ - { success: { objectId: "parent" } }, - ]); + 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([ { @@ -2261,22 +2184,22 @@ describe("ParseObject", () => { }, ]) ); - const p = new ParseObject("Person"); - p.id = "P55"; - p.increment("count"); + const p = new ParseObject('Person'); + p.id = 'P55'; + p.increment('count'); p.save() .then(() => { - expect(p.get("count")).toBe(11); + expect(p.get('count')).toBe(11); return p.fetch(); }) .then(() => { - expect(p.get("count")).toBe(20); + 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([ { @@ -2289,22 +2212,22 @@ describe("ParseObject", () => { ); const p = ParseObject.fromJSON({ - className: "Person", - objectId: "P200", - name: "Fred", + className: 'Person', + objectId: 'P200', + name: 'Fred', count: 0, }); - expect(p.get("name")).toBe("Fred"); - expect(p.get("count")).toBe(0); + expect(p.get('name')).toBe('Fred'); + expect(p.get('count')).toBe(0); p.fetch().then(() => { - expect(p.get("count")).toBe(10); - expect(p.get("name")).toBe(undefined); - expect(p.has("name")).toBe(false); + expect(p.get('count')).toBe(10); + expect(p.get('name')).toBe(undefined); + expect(p.has('name')).toBe(false); done(); }); }); - it("can destroy an object", async () => { + it('can destroy an object', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -2313,15 +2236,15 @@ describe("ParseObject", () => { RESTController._setXHR(function () { return xhr; }); - const p = new ParseObject("Person"); - p.id = "pid"; + 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", + 'POST', + 'https://api.parse.com/1/classes/Person/pid', true, ]); - expect(JSON.parse(xhr.send.mock.calls[0])._method).toBe("DELETE"); + expect(JSON.parse(xhr.send.mock.calls[0])._method).toBe('DELETE'); }); jest.runAllTicks(); await flushPromises(); @@ -2333,7 +2256,7 @@ describe("ParseObject", () => { await result; }); - it("accepts context on destroy", async () => { + it('accepts context on destroy', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ @@ -2345,29 +2268,29 @@ describe("ParseObject", () => { ); // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); // Save object - const context = { a: "a" }; - const obj = new ParseObject("Item"); - obj.id = "pid"; + const context = { a: 'a' }; + const obj = new ParseObject('Item'); + obj.id = 'pid'; await obj.destroy({ context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it("handle destroy on new object", async () => { + it('handle destroy on new object', async () => { const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); - const obj = new ParseObject("Item"); + const obj = new ParseObject('Item'); await obj.destroy({ useMasterKey: true }); 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(), @@ -2378,17 +2301,13 @@ describe("ParseObject", () => { }); const objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); + 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", + method: 'POST', + path: '/1/classes/Person', body: {}, }); done(); @@ -2397,18 +2316,18 @@ describe("ParseObject", () => { await flushPromises(); xhr.status = 200; xhr.responseText = JSON.stringify([ - { success: { objectId: "pid0" } }, - { success: { objectId: "pid1" } }, - { success: { objectId: "pid2" } }, - { success: { objectId: "pid3" } }, - { success: { objectId: "pid4" } }, + { success: { objectId: 'pid0' } }, + { success: { objectId: 'pid1' } }, + { success: { objectId: 'pid2' } }, + { success: { objectId: 'pid3' } }, + { success: { objectId: 'pid4' } }, ]); xhr.readyState = 4; xhr.onreadystatechange(); 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] = { @@ -2425,59 +2344,51 @@ describe("ParseObject", () => { }); const objects = []; for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject("Person"); + 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(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "pid0" } }, - { success: { objectId: "pid1" } }, - { success: { objectId: "pid2" } }, - { success: { objectId: "pid3" } }, - { success: { objectId: "pid4" } }, - { success: { objectId: "pid5" } }, - { success: { objectId: "pid6" } }, - { success: { objectId: "pid7" } }, - { success: { objectId: "pid8" } }, - { success: { objectId: "pid9" } }, - { success: { objectId: "pid10" } }, - { success: { objectId: "pid11" } }, - { success: { objectId: "pid12" } }, - { success: { objectId: "pid13" } }, - { success: { objectId: "pid14" } }, - { success: { objectId: "pid15" } }, - { success: { objectId: "pid16" } }, - { success: { objectId: "pid17" } }, - { success: { objectId: "pid18" } }, - { success: { objectId: "pid19" } }, + { success: { objectId: 'pid0' } }, + { success: { objectId: 'pid1' } }, + { success: { objectId: 'pid2' } }, + { success: { objectId: 'pid3' } }, + { success: { objectId: 'pid4' } }, + { success: { objectId: 'pid5' } }, + { success: { objectId: 'pid6' } }, + { success: { objectId: 'pid7' } }, + { success: { objectId: 'pid8' } }, + { success: { objectId: 'pid9' } }, + { success: { objectId: 'pid10' } }, + { success: { objectId: 'pid11' } }, + { success: { objectId: 'pid12' } }, + { success: { objectId: 'pid13' } }, + { success: { objectId: 'pid14' } }, + { success: { objectId: 'pid15' } }, + { success: { objectId: 'pid16' } }, + { success: { objectId: 'pid17' } }, + { success: { objectId: 'pid18' } }, + { success: { objectId: 'pid19' } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); xhrs[1].responseText = JSON.stringify([ - { success: { objectId: "pid20" } }, - { success: { objectId: "pid21" } }, + { success: { objectId: 'pid20' } }, + { success: { objectId: 'pid21' } }, ]); xhrs[1].onreadystatechange(); 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] = { @@ -2494,59 +2405,51 @@ describe("ParseObject", () => { }); const objects = []; for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject("Person"); + 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(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "pid0" } }, - { success: { objectId: "pid1" } }, - { success: { objectId: "pid2" } }, - { success: { objectId: "pid3" } }, - { success: { objectId: "pid4" } }, - { success: { objectId: "pid5" } }, - { success: { objectId: "pid6" } }, - { success: { objectId: "pid7" } }, - { success: { objectId: "pid8" } }, - { success: { objectId: "pid9" } }, - { success: { objectId: "pid10" } }, - { success: { objectId: "pid11" } }, - { success: { objectId: "pid12" } }, - { success: { objectId: "pid13" } }, - { success: { objectId: "pid14" } }, - { success: { objectId: "pid15" } }, - { success: { objectId: "pid16" } }, - { success: { objectId: "pid17" } }, - { success: { objectId: "pid18" } }, - { success: { objectId: "pid19" } }, + { success: { objectId: 'pid0' } }, + { success: { objectId: 'pid1' } }, + { success: { objectId: 'pid2' } }, + { success: { objectId: 'pid3' } }, + { success: { objectId: 'pid4' } }, + { success: { objectId: 'pid5' } }, + { success: { objectId: 'pid6' } }, + { success: { objectId: 'pid7' } }, + { success: { objectId: 'pid8' } }, + { success: { objectId: 'pid9' } }, + { success: { objectId: 'pid10' } }, + { success: { objectId: 'pid11' } }, + { success: { objectId: 'pid12' } }, + { success: { objectId: 'pid13' } }, + { success: { objectId: 'pid14' } }, + { success: { objectId: 'pid15' } }, + { success: { objectId: 'pid16' } }, + { success: { objectId: 'pid17' } }, + { success: { objectId: 'pid18' } }, + { success: { objectId: 'pid19' } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); xhrs[1].responseText = JSON.stringify([ - { success: { objectId: "pid20" } }, - { success: { objectId: "pid21" } }, + { success: { objectId: 'pid20' } }, + { success: { objectId: 'pid21' } }, ]); xhrs[1].onreadystatechange(); 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] = { @@ -2563,52 +2466,52 @@ describe("ParseObject", () => { }); const objects = []; for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject("Person"); + 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); expect(objects[20].dirty()).toBe(true); - expect(error.message).toBe("first error"); + expect(error.message).toBe('first error'); done(); }); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "pid0" } }, - { success: { objectId: "pid1" } }, - { success: { objectId: "pid2" } }, - { success: { objectId: "pid3" } }, - { success: { objectId: "pid4" } }, - { success: { objectId: "pid5" } }, - { error: { code: -1, error: "first error" } }, - { success: { objectId: "pid7" } }, - { success: { objectId: "pid8" } }, - { success: { objectId: "pid9" } }, - { success: { objectId: "pid10" } }, - { success: { objectId: "pid11" } }, - { success: { objectId: "pid12" } }, - { success: { objectId: "pid13" } }, - { success: { objectId: "pid14" } }, - { error: { code: -1, error: "second error" } }, - { success: { objectId: "pid16" } }, - { success: { objectId: "pid17" } }, - { success: { objectId: "pid18" } }, - { success: { objectId: "pid19" } }, + { success: { objectId: 'pid0' } }, + { success: { objectId: 'pid1' } }, + { success: { objectId: 'pid2' } }, + { success: { objectId: 'pid3' } }, + { success: { objectId: 'pid4' } }, + { success: { objectId: 'pid5' } }, + { error: { code: -1, error: 'first error' } }, + { success: { objectId: 'pid7' } }, + { success: { objectId: 'pid8' } }, + { success: { objectId: 'pid9' } }, + { success: { objectId: 'pid10' } }, + { success: { objectId: 'pid11' } }, + { success: { objectId: 'pid12' } }, + { success: { objectId: 'pid13' } }, + { success: { objectId: 'pid14' } }, + { error: { code: -1, error: 'second error' } }, + { success: { objectId: 'pid16' } }, + { success: { objectId: 'pid17' } }, + { success: { objectId: 'pid18' } }, + { success: { objectId: 'pid19' } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); }); }); -describe("ObjectController", () => { +describe('ObjectController', () => { beforeEach(() => { 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(), @@ -2618,16 +2521,16 @@ describe("ObjectController", () => { RESTController._setXHR(function () { return xhr; }); - const o = new ParseObject("Person"); - o.id = "pid"; + 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", + 'POST', + 'https://api.parse.com/1/classes/Person/pid', true, ]); const body = JSON.parse(xhr.send.mock.calls[0]); - expect(body._method).toBe("GET"); + expect(body._method).toBe('GET'); done(); }); await flushPromises(); @@ -2639,7 +2542,7 @@ describe("ObjectController", () => { jest.runAllTicks(); }); - it("accepts context on fetch", async () => { + it('accepts context on fetch', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( mockXHR([ @@ -2651,34 +2554,34 @@ describe("ObjectController", () => { ); // Spy on REST controller const controller = CoreManager.getRESTController(); - jest.spyOn(controller, "ajax"); + jest.spyOn(controller, 'ajax'); // Save object - const context = { a: "fetch" }; - const obj = new ParseObject("Item"); - obj.id = "pid"; + const context = { a: 'fetch' }; + const obj = new ParseObject('Item'); + obj.id = 'pid'; await obj.fetch({ context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); 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; + 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"); - expect(results[0].className).toBe("Person"); + expect(results[0].id).toBe('pid0'); + expect(results[0].className).toBe('Person'); done(); }); }); - 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(), @@ -2688,16 +2591,16 @@ describe("ObjectController", () => { RESTController._setXHR(function () { return xhr; }); - const o = new ParseObject("Person"); - o.id = "pid"; - objectController.fetch(o, false, { include: ["child"] }).then(() => { + 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", + 'POST', + 'https://api.parse.com/1/classes/Person/pid', true, ]); const body = JSON.parse(xhr.send.mock.calls[0]); - expect(body._method).toBe("GET"); + expect(body._method).toBe('GET'); done(); }); await flushPromises(); @@ -2709,23 +2612,23 @@ describe("ObjectController", () => { jest.runAllTicks(); }); - it("can fetch an array of objects with include", async () => { + it('can fetch an array of objects with include', async () => { const objectController = CoreManager.getObjectController(); const objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); - objects[i].id = "pid" + i; + objects[i] = new ParseObject('Person'); + objects[i].id = 'pid' + i; } const results = await objectController.fetch(objects, false, { - include: ["child"], + include: ['child'], }); expect(results.length).toBe(5); expect(results[0] instanceof ParseObject).toBe(true); - expect(results[0].id).toBe("pid0"); - expect(results[0].className).toBe("Person"); + expect(results[0].id).toBe('pid0'); + expect(results[0].className).toBe('Person'); }); - it("can destroy an object", async () => { + it('can destroy an object', async () => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), @@ -2735,19 +2638,19 @@ describe("ObjectController", () => { RESTController._setXHR(function () { return xhr; }); - const p = new ParseObject("Person"); - p.id = "pid"; + 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", + '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"; + 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, }); @@ -2759,13 +2662,13 @@ describe("ObjectController", () => { }) .then(() => { expect(xhr.open.mock.calls[1]).toEqual([ - "POST", - "https://api.parse.com/1/classes/Person/pid2", + '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"); + expect(body._method).toBe('DELETE'); + expect(body._MasterKey).toBe('C'); }); jest.runAllTicks(); await flushPromises(); @@ -2777,7 +2680,7 @@ describe("ObjectController", () => { await result; }); - it("can destroy an array of objects with batchSize", async () => { + it('can destroy an array of objects with batchSize', async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { @@ -2796,49 +2699,45 @@ describe("ObjectController", () => { }); let objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); - objects[i].id = "pid" + 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(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", + method: 'DELETE', + path: '/1/classes/Person/pid0', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid1", + method: 'DELETE', + path: '/1/classes/Person/pid1', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid2", + method: 'DELETE', + path: '/1/classes/Person/pid2', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid3", + method: 'DELETE', + path: '/1/classes/Person/pid3', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid4", + 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[i] = new ParseObject('Person'); + objects[i].id = 'pid' + i; } const destroy = objectController.destroy(objects, { batchSize: 20 }); jest.runAllTicks(); @@ -2863,7 +2762,7 @@ describe("ObjectController", () => { await result; }); - it("can destroy an array of objects", async () => { + it('can destroy an array of objects', async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { @@ -2882,49 +2781,45 @@ describe("ObjectController", () => { }); let objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); - objects[i].id = "pid" + 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(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", + method: 'DELETE', + path: '/1/classes/Person/pid0', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid1", + method: 'DELETE', + path: '/1/classes/Person/pid1', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid2", + method: 'DELETE', + path: '/1/classes/Person/pid2', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid3", + method: 'DELETE', + path: '/1/classes/Person/pid3', body: {}, }, { - method: "DELETE", - path: "/1/classes/Person/pid4", + 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[i] = new ParseObject('Person'); + objects[i].id = 'pid' + i; } const destroy = objectController.destroy(objects, {}); jest.runAllTicks(); @@ -2949,7 +2844,7 @@ describe("ObjectController", () => { await result; }); - it("can save an object", async () => { + it('can save an object', async () => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), @@ -2959,17 +2854,17 @@ describe("ObjectController", () => { RESTController._setXHR(function () { return xhr; }); - const p = new ParseObject("Person"); - p.id = "pid"; - p.set("key", "value"); + 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", + 'POST', + 'https://api.parse.com/1/classes/Person/pid', true, ]); const body = JSON.parse(xhr.send.mock.calls[0]); - expect(body.key).toBe("value"); + expect(body.key).toBe('value'); }); jest.runAllTicks(); await flushPromises(); @@ -2981,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(); @@ -2989,7 +2884,7 @@ describe("ObjectController", () => { jest.runAllTicks(); }); - it("can save an array of files", async () => { + it('can save an array of files', async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 4; i++) { @@ -3006,22 +2901,22 @@ describe("ObjectController", () => { 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('parse.txt', { base64: 'ParseA==' }), + new ParseFile('parse2.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(); - const names = ["parse.txt", "parse2.txt", "parse3.txt"]; + const names = ['parse.txt', 'parse2.txt', 'parse3.txt']; for (let i = 0; i < 3; i++) { xhrs[i].responseText = JSON.stringify({ - name: "parse.txt", - url: "http://files.parsetfss.com/a/" + names[i], + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/' + names[i], }); await flushPromises(); xhrs[i].onreadystatechange(); @@ -3030,7 +2925,7 @@ describe("ObjectController", () => { await result; }); - it("can save an array of objects", async () => { + it('can save an array of objects', async () => { const objectController = CoreManager.getObjectController(); const xhrs = []; for (let i = 0; i < 3; i++) { @@ -3048,22 +2943,22 @@ describe("ObjectController", () => { }); const objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); + objects[i] = new ParseObject('Person'); } const result = objectController .save(objects, {}) - .then(async (results) => { + .then(async results => { expect(results.length).toBe(5); - expect(results[0].id).toBe("pid0"); - expect(results[0].get("index")).toBe(0); + 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); + objects[i] = new ParseObject('Person'); + objects[i].set('index', i); response.push({ - success: { objectId: "pid" + i }, + success: { objectId: 'pid' + i }, }); } const save = objectController.save(objects, {}); @@ -3077,17 +2972,17 @@ describe("ObjectController", () => { // This means they can also be modified before the first batch returns expect( SingleInstanceStateController.getState({ - className: "Person", + className: 'Person', id: objects[20]._getId(), }).pendingOps.length ).toBe(1); - objects[20].set("index", 0); + 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[0].id).toBe('pid0'); expect(objects[20].dirty()).toBe(true); expect(objects[20].id).toBe(undefined); @@ -3095,28 +2990,28 @@ describe("ObjectController", () => { jest.runAllTicks(); await flushPromises(); expect(objects[20].dirty()).toBe(false); - expect(objects[20].get("index")).toBe(0); - expect(objects[20].id).toBe("pid20"); + expect(objects[20].get('index')).toBe(0); + expect(objects[20].id).toBe('pid20'); return save; }) - .then((results) => { + .then(results => { expect(results.length).toBe(22); }); jest.runAllTicks(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ - { success: { objectId: "pid0", index: 0 } }, - { success: { objectId: "pid1", index: 1 } }, - { success: { objectId: "pid2", index: 2 } }, - { success: { objectId: "pid3", index: 3 } }, - { success: { objectId: "pid4", index: 4 } }, + { success: { objectId: 'pid0', index: 0 } }, + { success: { objectId: 'pid1', index: 1 } }, + { success: { objectId: 'pid2', index: 2 } }, + { success: { objectId: 'pid3', index: 3 } }, + { success: { objectId: 'pid4', index: 4 } }, ]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await result; }); - it("does not fail when checking if arrays of pointers are dirty", async () => { + it('does not fail when checking if arrays of pointers are dirty', async () => { const xhrs = []; for (let i = 0; i < 2; i++) { xhrs[i] = { @@ -3131,17 +3026,17 @@ describe("ObjectController", () => { RESTController._setXHR(function () { return xhrs[current++]; }); - xhrs[0].responseText = JSON.stringify([{ success: { objectId: "i333" } }]); + 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" }], + className: 'Brand', + objectId: 'b123', + 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); + const items = brand.get('items'); + items.push(new ParseObject('Item')); + brand.set('items', items); expect(function () { brand.save(); }).not.toThrow(); @@ -3150,144 +3045,144 @@ describe("ObjectController", () => { xhrs[0].onreadystatechange(); }); - it("can create a new instance of an object", () => { + it('can create a new instance of an object', () => { const o = ParseObject.fromJSON({ - className: "Clone", - objectId: "C12", + className: 'Clone', + objectId: 'C12', }); const o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); o.set({ valid: true }); - expect(o2.get("valid")).toBe(true); + expect(o2.get('valid')).toBe(true); expect(o).not.toBe(o2); }); - it("cannot create a new instance of an object without className", () => { + it('cannot create a new instance of an object without className', () => { expect(() => { ParseObject.fromJSON({}); - }).toThrow("Cannot create an object without a className"); + }).toThrow('Cannot create an object without a className'); }); }); -describe("ParseObject (unique instance mode)", () => { +describe('ParseObject (unique instance mode)', () => { beforeEach(() => { ParseObject.disableSingleInstance(); }); - it("can be created with initial attributes", () => { + it('can be created with initial attributes', () => { const o = new ParseObject({ - className: "Item", + className: 'Item', value: 12, }); - expect(o.className).toBe("Item"); + expect(o.className).toBe('Item'); expect(o.attributes).toEqual({ value: 12 }); }); - it("can be inflated from server JSON", () => { + it('can be inflated from server JSON', () => { const json = { - className: "Item", - createdAt: "2013-12-14T04:51:19Z", - objectId: "I1", - size: "medium", + className: 'Item', + createdAt: '2013-12-14T04:51:19Z', + objectId: 'I1', + size: 'medium', }; const o = ParseObject.fromJSON(json); - expect(o.className).toBe("Item"); - expect(o.id).toBe("I1"); + expect(o.className).toBe('Item'); + expect(o.id).toBe('I1'); expect(o.attributes).toEqual({ - size: "medium", + size: 'medium', createdAt: 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); }); - it("can be rendered to JSON", () => { - let o = new ParseObject("Item"); + it('can be rendered to JSON', () => { + let o = new ParseObject('Item'); o.set({ - size: "large", + size: 'large', inStock: 18, }); expect(o.toJSON()).toEqual({ - size: "large", + size: 'large', inStock: 18, }); - o = new ParseObject("Item"); + o = new ParseObject('Item'); o._finishFetch({ - objectId: "O2", - size: "medium", + objectId: 'O2', + size: 'medium', inStock: 12, }); - expect(o.id).toBe("O2"); + expect(o.id).toBe('O2'); expect(o.toJSON()).toEqual({ - objectId: "O2", - size: "medium", + objectId: 'O2', + size: 'medium', inStock: 12, }); }); - it("can add, update, and remove attributes", () => { + it('can add, update, and remove attributes', () => { const o = new ParseObject({ - className: "Item", - objectId: "anObjectId", + className: 'Item', + objectId: 'anObjectId', value: 12, valid: true, }); o.set({ value: 14 }); - expect(o.get("value")).toBe(14); - o.unset("valid"); - expect(o.get("valid")).toBe(undefined); - expect(o.dirtyKeys()).toEqual(["value", "valid"]); - o.increment("value"); - expect(o.get("value")).toEqual(15); + expect(o.get('value')).toBe(14); + o.unset('valid'); + expect(o.get('valid')).toBe(undefined); + expect(o.dirtyKeys()).toEqual(['value', 'valid']); + o.increment('value'); + expect(o.get('value')).toEqual(15); o.clear(); - expect(o.get("value")).toBe(undefined); + expect(o.get('value')).toBe(undefined); const o2 = ParseObject.fromJSON({ - className: "Item", - tags: ["#tbt"], + className: 'Item', + tags: ['#tbt'], }); - o2.add("tags", "#nofilter"); - expect(o2.get("tags")).toEqual(["#tbt", "#nofilter"]); + o2.add('tags', '#nofilter'); + expect(o2.get('tags')).toEqual(['#tbt', '#nofilter']); o2.revert(); - o2.addUnique("tags", "#tbt"); - expect(o2.get("tags")).toEqual(["#tbt"]); + o2.addUnique('tags', '#tbt'); + expect(o2.get('tags')).toEqual(['#tbt']); o2.revert(); - o2.remove("tags", "#tbt"); - expect(o2.get("tags")).toEqual([]); + o2.remove('tags', '#tbt'); + 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", + objectId: 'P1', count: 1, }, }, ]) ); - const p = new ParseObject("Person"); - p.set("age", 38); - p.increment("count"); - p.save().then((obj) => { + const p = new ParseObject('Person'); + p.set('age', 38); + p.increment('count'); + p.save().then(obj => { expect(obj).toBe(p); - expect(obj.get("age")).toBe(38); - expect(obj.get("count")).toBe(1); - expect(obj.op("age")).toBe(undefined); + expect(obj.get('age')).toBe(38); + expect(obj.get('count')).toBe(1); + expect(obj.op('age')).toBe(undefined); expect(obj.dirty()).toBe(false); done(); }); }); - it("can save an array of objects", async () => { + it('can save an array of objects', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -3298,17 +3193,13 @@ describe("ParseObject (unique instance mode)", () => { }); const objects = []; for (let i = 0; i < 5; i++) { - objects[i] = new ParseObject("Person"); + 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", + method: 'POST', + path: '/1/classes/Person', body: {}, }); }); @@ -3316,11 +3207,11 @@ describe("ParseObject (unique instance mode)", () => { xhr.status = 200; xhr.responseText = JSON.stringify([ - { success: { objectId: "pid0" } }, - { success: { objectId: "pid1" } }, - { success: { objectId: "pid2" } }, - { success: { objectId: "pid3" } }, - { success: { objectId: "pid4" } }, + { success: { objectId: 'pid0' } }, + { success: { objectId: 'pid1' } }, + { success: { objectId: 'pid2' } }, + { success: { objectId: 'pid3' } }, + { success: { objectId: 'pid4' } }, ]); await flushPromises(); xhr.readyState = 4; @@ -3329,55 +3220,55 @@ describe("ParseObject (unique instance mode)", () => { await result; }); - it("preserves changes when changing the id", () => { + it('preserves changes when changing the id', () => { const o = new ParseObject({ - className: "Item", - objectId: "anObjectId", + className: 'Item', + objectId: 'anObjectId', value: 12, }); - o.id = "otherId"; - expect(o.get("value")).toBe(12); + o.id = 'otherId'; + expect(o.get('value')).toBe(12); }); - it("can maintain differences between two instances of an object", () => { + it('can maintain differences between two instances of an object', () => { const o = new ParseObject({ - className: "Item", - objectId: "anObjectId", + className: 'Item', + objectId: 'anObjectId', value: 12, }); const o2 = new ParseObject({ - className: "Item", - objectId: "anObjectId", + className: 'Item', + objectId: 'anObjectId', value: 12, }); o.set({ value: 100 }); - expect(o.get("value")).toBe(100); - expect(o2.get("value")).toBe(12); + expect(o.get('value')).toBe(100); + expect(o2.get('value')).toBe(12); - o2.set({ name: "foo" }); - expect(o.has("name")).toBe(false); - expect(o2.has("name")).toBe(true); + o2.set({ name: 'foo' }); + expect(o.has('name')).toBe(false); + expect(o2.has('name')).toBe(true); }); - it("can create a new instance of an object", () => { + it('can create a new instance of an object', () => { const o = ParseObject.fromJSON({ - className: "Clone", - objectId: "C14", + className: 'Clone', + objectId: 'C14', }); let o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); expect(o).not.toBe(o2); o.set({ valid: true }); - expect(o2.get("valid")).toBe(undefined); + expect(o2.get('valid')).toBe(undefined); o2 = o.newInstance(); - expect(o2.get("valid")).toBe(true); + expect(o2.get('valid')).toBe(true); }); }); class MyObject extends ParseObject { constructor() { - super("MyObject"); + super('MyObject'); } doSomething() { @@ -3385,107 +3276,101 @@ class MyObject extends ParseObject { } static readOnlyAttributes() { - return ["readonly", "static", "frozen"]; + return ['readonly', 'static', 'frozen']; } } -ParseObject.registerSubclass("MyObject", MyObject); +ParseObject.registerSubclass('MyObject', MyObject); -describe("ParseObject Subclasses", () => { +describe('ParseObject Subclasses', () => { beforeEach(() => { ParseObject.enableSingleInstance(); }); - it("can be extended with ES6 classes", () => { + it('can be extended with ES6 classes', () => { const o = new MyObject(); - expect(o.className).toBe("MyObject"); - expect(MyObject.className).toBe("MyObject"); - o.id = "anObjectId"; + expect(o.className).toBe('MyObject'); + expect(MyObject.className).toBe('MyObject'); + o.id = 'anObjectId'; expect(o.toPointer()).toEqual({ - __type: "Pointer", - className: "MyObject", - objectId: "anObjectId", + __type: 'Pointer', + className: 'MyObject', + objectId: 'anObjectId', }); expect(o.doSomething()).toBe(5); - const o2 = MyObject.createWithoutData("otherId"); + const o2 = MyObject.createWithoutData('otherId'); expect(o2 instanceof ParseObject).toBe(true); expect(o2 instanceof MyObject).toBe(true); expect(o2.toPointer()).toEqual({ - __type: "Pointer", - className: "MyObject", - objectId: "otherId", + __type: 'Pointer', + className: 'MyObject', + objectId: 'otherId', }); expect(o2.doSomething()).toBe(5); }); - it("respects readonly attributes of 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" - ); + 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'); }); - it("registerSubclass errors", () => { + it('registerSubclass errors', () => { expect(() => { ParseObject.registerSubclass(1234); - }).toThrow("The first argument must be a valid class name."); + }).toThrow('The first argument must be a valid class name.'); expect(() => { - ParseObject.registerSubclass("TestObject", undefined); - }).toThrow("You must supply a subclass constructor."); + ParseObject.registerSubclass('TestObject', undefined); + }).toThrow('You must supply a subclass constructor.'); expect(() => { - ParseObject.registerSubclass("TestObject", {}); + ParseObject.registerSubclass('TestObject', {}); }).toThrow( - "You must register the subclass constructor. Did you attempt to register an instance of the subclass?" + 'You must register the subclass constructor. Did you attempt to register an instance of the subclass?' ); }); - it("can inflate subclasses from server JSON", () => { + it('can inflate subclasses from server JSON', () => { const json = { - className: "MyObject", - objectId: "anotherId", + className: 'MyObject', + objectId: 'anotherId', }; const o = ParseObject.fromJSON(json); expect(o instanceof ParseObject).toBe(true); - expect(o.className).toBe("MyObject"); - expect(o.id).toBe("anotherId"); + expect(o.className).toBe('MyObject'); + expect(o.id).toBe('anotherId'); expect(o.doSomething()).toBe(5); }); - it("can be cloned", () => { + it('can be cloned', () => { const o = new MyObject(); o.set({ - size: "large", + size: 'large', count: 7, }); const o2 = o.clone(); expect(o2 instanceof MyObject).toBe(true); - expect(o2.className).toBe("MyObject"); + expect(o2.className).toBe('MyObject'); expect(o2.attributes).toEqual({ - size: "large", + size: 'large', count: 7, }); expect(o2.id).toBe(undefined); expect(o.equals(o2)).toBe(false); }); - it("can be cleared", () => { + it('can be cleared', () => { const o = new MyObject(); o.set({ - size: "large", + size: 'large', count: 7, }); - jest.spyOn(o, "set"); + jest.spyOn(o, 'set'); o.clear(); expect(o.set).toHaveBeenCalledWith( { @@ -3499,36 +3384,36 @@ describe("ParseObject Subclasses", () => { }); }); -describe("ParseObject extensions", () => { +describe('ParseObject extensions', () => { beforeEach(() => { ParseObject.enableSingleInstance(); }); - it("can generate ParseObjects with a default className", () => { - const YourObject = ParseObject.extend("YourObject"); + it('can generate ParseObjects with a default className', () => { + const YourObject = ParseObject.extend('YourObject'); const yo = new YourObject(); expect(yo instanceof ParseObject).toBe(true); expect(yo instanceof YourObject).toBe(true); - expect(yo.className).toBe("YourObject"); - yo.set("greeting", "yo"); - expect(yo.get("greeting")).toBe("yo"); + expect(yo.className).toBe('YourObject'); + yo.set('greeting', 'yo'); + expect(yo.get('greeting')).toBe('yo'); expect(yo.attributes).toEqual({ - greeting: "yo", + greeting: 'yo', }); - const yo2 = YourObject.createWithoutData("otherId"); + const yo2 = YourObject.createWithoutData('otherId'); expect(yo2 instanceof ParseObject).toBe(true); expect(yo2 instanceof YourObject).toBe(true); expect(yo2.toPointer()).toEqual({ - __type: "Pointer", - className: "YourObject", - objectId: "otherId", + __type: 'Pointer', + className: 'YourObject', + objectId: 'otherId', }); }); - it("can extend the prototype and statics of ParseObject", () => { + it('can extend the prototype and statics of ParseObject', () => { const ExtendedObject = ParseObject.extend( - "ExtendedObject", + 'ExtendedObject', { getFoo() { return 12; @@ -3536,7 +3421,7 @@ describe("ParseObject extensions", () => { }, { isFoo(value) { - return value === "foo"; + return value === 'foo'; }, } ); @@ -3545,112 +3430,104 @@ describe("ParseObject extensions", () => { expect(e instanceof ExtendedObject).toBe(true); expect(e.getFoo()).toBe(12); expect(ExtendedObject.isFoo(12)).toBe(false); - expect(ExtendedObject.isFoo("foo")).toBe(true); + expect(ExtendedObject.isFoo('foo')).toBe(true); }); - it("can extend a previous extension", () => { - let FeatureObject = ParseObject.extend("FeatureObject", { + it('can extend a previous extension', () => { + let FeatureObject = ParseObject.extend('FeatureObject', { foo() { - return "F"; + return 'F'; }, }); let f = new FeatureObject(); - expect(f.foo()).toBe("F"); - FeatureObject = ParseObject.extend("FeatureObject", { + expect(f.foo()).toBe('F'); + FeatureObject = ParseObject.extend('FeatureObject', { bar() { - return "B"; + return 'B'; }, }); f = new FeatureObject(); - expect(f.foo() + f.bar()).toBe("FB"); + expect(f.foo() + f.bar()).toBe('FB'); }); - it("can specify a custom initializer", () => { - const InitObject = ParseObject.extend("InitObject", { + it('can specify a custom initializer', () => { + const InitObject = ParseObject.extend('InitObject', { initialize: function () { - this.set("field", 12); + this.set('field', 12); }, }); const i = new InitObject(); - expect(i.get("field")).toBe(12); + expect(i.get('field')).toBe(12); }); - it("can handle className parameters", () => { + it('can handle className parameters', () => { expect(() => { ParseObject.extend(); }).toThrow("Parse.Object.extend's first argument should be the className."); - let CustomObject = ParseObject.extend("Item"); - expect(CustomObject.className).toBe("Item"); + let CustomObject = ParseObject.extend('Item'); + expect(CustomObject.className).toBe('Item'); - CustomObject = ParseObject.extend({ className: "Test" }); - expect(CustomObject.className).toBe("Test"); + CustomObject = ParseObject.extend({ className: 'Test' }); + expect(CustomObject.className).toBe('Test'); }); - it("can extend with user rewrite", () => { - const CustomObject = ParseObject.extend("User"); - expect(CustomObject.className).toBe("_User"); + it('can extend with user rewrite', () => { + const CustomObject = ParseObject.extend('User'); + expect(CustomObject.className).toBe('_User'); }); - it("can extend multiple subclasses", () => { - const CustomObject = ParseObject.extend("Item"); + it('can extend multiple subclasses', () => { + const CustomObject = ParseObject.extend('Item'); expect(() => { - new CustomObject({ "invalid#name": "bar" }); + new CustomObject({ 'invalid#name': 'bar' }); }).toThrow("Can't create an invalid Parse Object"); - const CustomUserObject = CustomObject.extend("User"); + const CustomUserObject = CustomObject.extend('User'); const CustomRewrite = CustomUserObject.extend(); - expect(CustomRewrite.className).toBe("_User"); + expect(CustomRewrite.className).toBe('_User'); }); }); -describe("ParseObject pin", () => { +describe('ParseObject pin', () => { beforeEach(() => { ParseObject.enableSingleInstance(); jest.clearAllMocks(); mockLocalDatastore.isEnabled = true; }); - it("can pin to default", async () => { - const object = new ParseObject("Item"); + it('can pin to default', async () => { + const object = new ParseObject('Item'); await object.pin(); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalDatastore._handlePinAllWithName - ).toHaveBeenCalledWith(DEFAULT_PIN, [object]); + expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledWith(DEFAULT_PIN, [object]); }); - it("can unPin to default", async () => { - const object = new ParseObject("Item"); + it('can unPin to default', async () => { + const object = new ParseObject('Item'); await object.unPin(); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalDatastore._handleUnPinAllWithName - ).toHaveBeenCalledWith(DEFAULT_PIN, [object]); + expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledWith(DEFAULT_PIN, [object]); }); - it("can pin to specific pin", async () => { - const object = new ParseObject("Item"); - await object.pinWithName("test_pin"); + it('can pin to specific pin', async () => { + const object = new ParseObject('Item'); + await object.pinWithName('test_pin'); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalDatastore._handlePinAllWithName - ).toHaveBeenCalledWith("test_pin", [object]); + expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledWith('test_pin', [object]); }); - it("can unPin to specific", async () => { - const object = new ParseObject("Item"); - await object.unPinWithName("test_pin"); + it('can unPin to specific', async () => { + const object = new ParseObject('Item'); + await object.unPinWithName('test_pin'); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); - expect( - mockLocalDatastore._handleUnPinAllWithName - ).toHaveBeenCalledWith("test_pin", [object]); + expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledWith('test_pin', [object]); }); - it("can check if pinned", async () => { - const object = new ParseObject("Item"); - object.id = "1234"; + it('can check if pinned', async () => { + const object = new ParseObject('Item'); + object.id = '1234'; mockLocalDatastore.fromPinWithName .mockImplementationOnce(() => { return [object._toFullJSON()]; @@ -3663,34 +3540,30 @@ describe("ParseObject pin", () => { expect(isPinned).toEqual(false); }); - it("can fetchFromLocalDatastore", async () => { - const object = new ParseObject("Item"); - object.id = "123"; - mockLocalDatastore.getKeyForObject.mockImplementationOnce(() => "Item_123"); + it('can fetchFromLocalDatastore', async () => { + const object = new ParseObject('Item'); + object.id = '123'; + mockLocalDatastore.getKeyForObject.mockImplementationOnce(() => 'Item_123'); - mockLocalDatastore._serializeObject.mockImplementationOnce(() => - object._toFullJSON() - ); + mockLocalDatastore._serializeObject.mockImplementationOnce(() => object._toFullJSON()); await object.fetchFromLocalDatastore(); expect(mockLocalDatastore._serializeObject).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._serializeObject).toHaveBeenCalledWith( - "Item_123" - ); + expect(mockLocalDatastore._serializeObject).toHaveBeenCalledWith('Item_123'); }); - it("cannot fetchFromLocalDatastore if unsaved", async () => { + it('cannot fetchFromLocalDatastore if unsaved', async () => { try { - const object = new ParseObject("Item"); + const object = new ParseObject('Item'); await object.fetchFromLocalDatastore(); } catch (e) { - expect(e.message).toBe("Cannot fetch an unsaved ParseObject"); + expect(e.message).toBe('Cannot fetch an unsaved ParseObject'); } }); - it("can pinAll", async () => { - const obj1 = new ParseObject("Item"); - const obj2 = new ParseObject("Item"); + it('can pinAll', async () => { + const obj1 = new ParseObject('Item'); + const obj2 = new ParseObject('Item'); await ParseObject.pinAll([obj1, obj2]); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); expect(mockLocalDatastore._handlePinAllWithName.mock.calls[0]).toEqual([ @@ -3699,9 +3572,9 @@ describe("ParseObject pin", () => { ]); }); - it("can unPinAll", async () => { - const obj1 = new ParseObject("Item"); - const obj2 = new ParseObject("Item"); + it('can unPinAll', async () => { + const obj1 = new ParseObject('Item'); + const obj2 = new ParseObject('Item'); await ParseObject.unPinAll([obj1, obj2]); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); expect(mockLocalDatastore._handleUnPinAllWithName.mock.calls[0]).toEqual([ @@ -3710,105 +3583,99 @@ describe("ParseObject pin", () => { ]); }); - it("can unPinAllObjects", async () => { + it('can unPinAllObjects', async () => { await ParseObject.unPinAllObjects(); expect(mockLocalDatastore.unPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([ - DEFAULT_PIN, - ]); + expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([DEFAULT_PIN]); }); - it("can unPinAllObjectsWithName", async () => { - await ParseObject.unPinAllObjectsWithName("123"); + it('can unPinAllObjectsWithName', async () => { + await ParseObject.unPinAllObjectsWithName('123'); expect(mockLocalDatastore.unPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([ - PIN_PREFIX + "123", - ]); + expect(mockLocalDatastore.unPinWithName.mock.calls[0]).toEqual([PIN_PREFIX + '123']); }); - it("cannot pin when localDatastore disabled", async () => { + it('cannot pin when localDatastore disabled', async () => { mockLocalDatastore.isEnabled = false; - const name = "test_pin"; - const obj = new ParseObject("Item"); + const name = 'test_pin'; + const obj = new ParseObject('Item'); try { await obj.pin(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await obj.unPin(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await obj.isPinned(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await obj.pinWithName(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await obj.unPinWithName(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await obj.fetchFromLocalDatastore(); } catch (error) { - expect(error.message).toBe( - "Parse.enableLocalDatastore() must be called first" - ); + expect(error.message).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.pinAll([obj]); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.unPinAll([obj]); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.pinAllWithName(name, [obj]); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.unPinAllWithName(name, [obj]); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.unPinAllObjects(); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } try { await ParseObject.unPinAllObjectsWithName(name); } catch (error) { - expect(error).toBe("Parse.enableLocalDatastore() must be called first"); + 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", + objectId: 'P5', }, }, ]) ); - const p = new ParseObject("Person"); - p.save(null, { cascadeSave: false }).then((obj) => { + const p = new ParseObject('Person'); + p.save(null, { cascadeSave: false }).then(obj => { expect(obj).toBe(p); - expect(obj.id).toBe("P5"); + expect(obj.id).toBe('P5'); done(); }); }); diff --git a/src/__tests__/ParseOp-test.js b/src/__tests__/ParseOp-test.js index 16097a8e5..6f9728d45 100644 --- a/src/__tests__/ParseOp-test.js +++ b/src/__tests__/ParseOp-test.js @@ -7,18 +7,18 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../arrayContainsObject"); -jest.dontMock("../encode"); -jest.dontMock("../decode"); -jest.dontMock("../ParseOp"); -jest.dontMock("../unique"); +jest.dontMock('../arrayContainsObject'); +jest.dontMock('../encode'); +jest.dontMock('../decode'); +jest.dontMock('../ParseOp'); +jest.dontMock('../unique'); let localCount = 0; const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { - this._localId = "local" + localCount++; + this._localId = 'local' + localCount++; } }; mockObject.prototype._getId = function () { @@ -28,17 +28,17 @@ mockObject.fromJSON = function (json) { return new mockObject(json.className, json.objectId); }; mockObject.registerSubclass = function () {}; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); const mockRelation = function (parent, key) { this.parent = parent; this.key = key; }; -jest.setMock("../ParseRelation", mockRelation); +jest.setMock('../ParseRelation', mockRelation); -const ParseRelation = require("../ParseRelation"); -const ParseObject = require("../ParseObject"); -const ParseOp = require("../ParseOp"); +const ParseRelation = require('../ParseRelation'); +const ParseObject = require('../ParseObject'); +const ParseOp = require('../ParseOp'); const { Op, SetOp, @@ -51,8 +51,8 @@ const { opFromJSON, } = ParseOp; -describe("ParseOp", () => { - it("base class", () => { +describe('ParseOp', () => { + it('base class', () => { const op = new Op(); expect(op.applyTo instanceof Function).toBe(true); expect(op.mergeWith instanceof Function).toBe(true); @@ -61,11 +61,11 @@ describe("ParseOp", () => { expect(op.mergeWith()).toBeUndefined(); expect(op.toJSON()).toBeUndefined(); expect(opFromJSON({})).toBe(null); - expect(opFromJSON({ __op: "Unknown" })).toBe(null); + expect(opFromJSON({ __op: 'Unknown' })).toBe(null); expect(opFromJSON(op.toJSON())).toBe(null); }); - it("is extended by all Ops", () => { + it('is extended by all Ops', () => { expect(new SetOp(1) instanceof Op).toBe(true); expect(new UnsetOp() instanceof Op).toBe(true); expect(new IncrementOp(1) instanceof Op).toBe(true); @@ -74,13 +74,13 @@ describe("ParseOp", () => { expect(new RemoveOp(1) instanceof Op).toBe(true); }); - it("can create and apply Set Ops", () => { + it('can create and apply Set Ops', () => { const set = new SetOp(14); expect(set.applyTo(null)).toBe(14); expect(set.applyTo(undefined)).toBe(14); expect(set.applyTo(41)).toBe(14); - expect(set.applyTo("14")).toBe(14); + expect(set.applyTo('14')).toBe(14); // SetOp overrides all expect(set.mergeWith(new SetOp(12))._value).toBe(14); @@ -93,13 +93,13 @@ describe("ParseOp", () => { expect(set.toJSON()).toBe(14); }); - it("can create and apply Unset Ops", () => { + it('can create and apply Unset Ops', () => { const unset = new UnsetOp(); expect(unset.applyTo(null)).toBe(undefined); expect(unset.applyTo(undefined)).toBe(undefined); expect(unset.applyTo(14)).toBe(undefined); - expect(unset.applyTo("14")).toBe(undefined); + expect(unset.applyTo('14')).toBe(undefined); // UnsetOp overrides all expect(unset.mergeWith(new SetOp(12)) instanceof UnsetOp).toBe(true); @@ -109,24 +109,20 @@ describe("ParseOp", () => { expect(unset.mergeWith(new AddUniqueOp(1)) instanceof UnsetOp).toBe(true); expect(unset.mergeWith(new RemoveOp(1)) instanceof UnsetOp).toBe(true); - expect(unset.toJSON()).toEqual({ __op: "Delete" }); + expect(unset.toJSON()).toEqual({ __op: 'Delete' }); expect(opFromJSON(unset.toJSON())).toEqual(unset); }); - it("can create and apply Increment Ops", () => { + it('can create and apply Increment Ops', () => { expect(function () { new IncrementOp(); - }).toThrow("Increment Op must be initialized with a numeric amount."); + }).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."); + 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); @@ -134,8 +130,8 @@ describe("ParseOp", () => { expect(bigInc.applyTo(-98)).toBe(1); expect(bigInc.applyTo()).toBe(99); - expect(inc.toJSON()).toEqual({ __op: "Increment", amount: 1 }); - expect(bigInc.toJSON()).toEqual({ __op: "Increment", amount: 99 }); + expect(inc.toJSON()).toEqual({ __op: 'Increment', amount: 1 }); + expect(bigInc.toJSON()).toEqual({ __op: 'Increment', amount: 99 }); expect(opFromJSON(bigInc.toJSON())).toEqual(bigInc); let merge = inc.mergeWith(); @@ -155,27 +151,27 @@ describe("ParseOp", () => { expect(merge._amount).toBe(100); expect(inc.mergeWith.bind(inc, new AddOp(1))).toThrow( - "Cannot merge Increment Op with the previous Op" + 'Cannot merge Increment Op with the previous Op' ); expect(inc.mergeWith.bind(inc, new AddUniqueOp(1))).toThrow( - "Cannot merge Increment Op with the previous Op" + 'Cannot merge Increment Op with the previous Op' ); expect(inc.mergeWith.bind(inc, new RemoveOp(1))).toThrow( - "Cannot merge Increment Op with the previous Op" + 'Cannot merge Increment Op with the previous Op' ); }); - it("can create and apply Add Ops", () => { - const add = new AddOp("element"); + it('can create and apply Add Ops', () => { + const add = new AddOp('element'); - expect(add.applyTo(null)).toEqual(["element"]); - expect(add.applyTo(undefined)).toEqual(["element"]); + 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(add.applyTo([12])).toEqual([12, "element"]); + 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"] }); + expect(add.toJSON()).toEqual({ __op: 'Add', objects: ['element'] }); expect(opFromJSON(add.toJSON())).toEqual(add); const addMany = new AddOp([1, 2, 2, 3, 4, 5]); @@ -183,49 +179,49 @@ describe("ParseOp", () => { expect(addMany.applyTo([-2, -1, 0])).toEqual([-2, -1, 0, 1, 2, 2, 3, 4, 5]); expect(addMany.toJSON()).toEqual({ - __op: "Add", + __op: 'Add', objects: [1, 2, 2, 3, 4, 5], }); let merge = add.mergeWith(null); expect(merge instanceof AddOp).toBe(true); - expect(merge._value).toEqual(["element"]); + expect(merge._value).toEqual(['element']); - merge = add.mergeWith(new SetOp(["an"])); + merge = add.mergeWith(new SetOp(['an'])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(["an", "element"]); + expect(merge._value).toEqual(['an', 'element']); - merge = add.mergeWith(new UnsetOp(["an"])); + merge = add.mergeWith(new UnsetOp(['an'])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(["element"]); + expect(merge._value).toEqual(['element']); merge = add.mergeWith(addMany); expect(merge instanceof AddOp).toBe(true); - expect(merge._value).toEqual([1, 2, 2, 3, 4, 5, "element"]); + expect(merge._value).toEqual([1, 2, 2, 3, 4, 5, 'element']); expect(add.mergeWith.bind(add, new IncrementOp(1))).toThrow( - "Cannot merge Add Op with the previous Op" + 'Cannot merge Add Op with the previous Op' ); expect(add.mergeWith.bind(add, new AddUniqueOp(1))).toThrow( - "Cannot merge Add Op with the previous Op" + 'Cannot merge Add Op with the previous Op' ); expect(add.mergeWith.bind(add, new RemoveOp(1))).toThrow( - "Cannot merge Add Op with the previous Op" + 'Cannot merge Add Op with the previous Op' ); }); - it("can create and apply AddUnique Ops", () => { - const add = new AddUniqueOp("element"); + it('can create and apply AddUnique Ops', () => { + const add = new AddUniqueOp('element'); - expect(add.applyTo(null)).toEqual(["element"]); - expect(add.applyTo(undefined)).toEqual(["element"]); + 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(add.applyTo([12])).toEqual([12, "element"]); - expect(add.applyTo([12, "element"])).toEqual([12, "element"]); + 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']); - expect(add.toJSON()).toEqual({ __op: "AddUnique", objects: ["element"] }); + expect(add.toJSON()).toEqual({ __op: 'AddUnique', objects: ['element'] }); expect(opFromJSON(add.toJSON())).toEqual(add); const addMany = new AddUniqueOp([1, 2, 2, 3, 4, 5]); @@ -235,77 +231,72 @@ describe("ParseOp", () => { expect(addMany.applyTo([-2, 1, 4, 0])).toEqual([-2, 1, 4, 0, 2, 3, 5]); expect(addMany.toJSON()).toEqual({ - __op: "AddUnique", + __op: 'AddUnique', objects: [1, 2, 3, 4, 5], }); let merge = add.mergeWith(null); expect(merge instanceof AddUniqueOp).toBe(true); - expect(merge._value).toEqual(["element"]); + expect(merge._value).toEqual(['element']); - merge = add.mergeWith(new SetOp(["an", "element"])); + merge = add.mergeWith(new SetOp(['an', 'element'])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(["an", "element"]); + expect(merge._value).toEqual(['an', 'element']); - merge = add.mergeWith(new UnsetOp(["an"])); + merge = add.mergeWith(new UnsetOp(['an'])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(["element"]); + 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"]); + expect(merge._value).toEqual([1, 2, 'element', 3, 'an']); expect(add.mergeWith.bind(add, new IncrementOp(1))).toThrow( - "Cannot merge AddUnique Op with the previous Op" + 'Cannot merge AddUnique Op with the previous Op' ); expect(add.mergeWith.bind(add, new AddOp(1))).toThrow( - "Cannot merge AddUnique Op with the previous Op" + 'Cannot merge AddUnique Op with the previous Op' ); expect(add.mergeWith.bind(add, new RemoveOp(1))).toThrow( - "Cannot merge AddUnique Op with the previous Op" + 'Cannot merge AddUnique Op with the previous Op' ); - let addObjects = new AddUniqueOp(new ParseObject("Item", "i2")); + let addObjects = new AddUniqueOp(new ParseObject('Item', 'i2')); expect( addObjects.applyTo([ - new ParseObject("Item", "i1"), - new ParseObject("Item", "i2"), - new ParseObject("Item", "i3"), + 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"), + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i3'), ]); - addObjects = new AddUniqueOp(new ParseObject("Item", "i2")); + addObjects = new AddUniqueOp(new ParseObject('Item', 'i2')); expect( - addObjects.applyTo([ - new ParseObject("Item", "i1"), - new ParseObject("Item", "i3"), - ]) + addObjects.applyTo([new ParseObject('Item', 'i1'), new ParseObject('Item', 'i3')]) ).toEqual([ - new ParseObject("Item", "i1"), - new ParseObject("Item", "i3"), - new ParseObject("Item", "i2"), + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i3'), + new ParseObject('Item', 'i2'), ]); }); - it("can create and apply Remove Ops", () => { - const rem = new RemoveOp("element"); + it('can create and apply Remove Ops', () => { + const rem = new RemoveOp('element'); expect(rem.applyTo(null)).toEqual([]); expect(rem.applyTo(undefined)).toEqual([]); expect(function () { - rem.applyTo("abc"); - }).toThrow("Cannot remove elements from a non-array value"); + 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]); + expect(rem.applyTo([12, 'element'])).toEqual([12]); + expect(rem.applyTo(['element', 12, 'element', 'element'])).toEqual([12]); - expect(rem.toJSON()).toEqual({ __op: "Remove", objects: ["element"] }); + expect(rem.toJSON()).toEqual({ __op: 'Remove', objects: ['element'] }); expect(opFromJSON(rem.toJSON())).toEqual(rem); const removeMany = new RemoveOp([1, 2, 2, 3, 4, 5]); @@ -313,19 +304,19 @@ describe("ParseOp", () => { expect(removeMany.applyTo([-2, 1, 4, 0])).toEqual([-2, 0]); expect(removeMany.toJSON()).toEqual({ - __op: "Remove", + __op: 'Remove', objects: [1, 2, 3, 4, 5], }); let merge = rem.mergeWith(null); expect(merge instanceof RemoveOp).toBe(true); - expect(merge._value).toEqual(["element"]); + expect(merge._value).toEqual(['element']); - merge = rem.mergeWith(new SetOp(["an", "element"])); + merge = rem.mergeWith(new SetOp(['an', 'element'])); expect(merge instanceof SetOp).toBe(true); - expect(merge._value).toEqual(["an"]); + expect(merge._value).toEqual(['an']); - merge = rem.mergeWith(new UnsetOp(["an"])); + merge = rem.mergeWith(new UnsetOp(['an'])); expect(merge instanceof UnsetOp).toBe(true); expect(merge._value).toEqual(undefined); @@ -334,36 +325,33 @@ describe("ParseOp", () => { expect(merge._value).toEqual([2, 4, 1, 3]); expect(rem.mergeWith.bind(rem, new IncrementOp(1))).toThrow( - "Cannot merge Remove Op with the previous Op" + 'Cannot merge Remove Op with the previous Op' ); - const removeObjects = new RemoveOp(new ParseObject("Item", "i2")); - const previousOp = new RemoveOp(new ParseObject("Item", "i5")); + 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"), + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i3'), ]) - ).toEqual([new ParseObject("Item", "i1"), 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"), + 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")]); + ).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", () => { + it('can create and apply Relation Ops', () => { let r = new RelationOp(); expect(r.relationsToAdd).toBe(undefined); expect(r.relationsToRemove).toBe(undefined); @@ -373,105 +361,93 @@ describe("ParseOp", () => { expect(r.relationsToRemove).toEqual([]); expect(function () { - new RelationOp([new ParseObject("Item")], []); - }).toThrow( - "You cannot add or remove an unsaved Parse Object from a relation" - ); + new RelationOp([new ParseObject('Item')], []); + }).toThrow('You cannot add or remove an unsaved Parse Object from a relation'); expect(function () { - const a = new ParseObject("Item"); - a.id = "I1"; - const b = new ParseObject("Delivery"); - b.id = "D1"; + 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"; + const o = new ParseObject('Item'); + o.id = 'I1'; + const o2 = new ParseObject('Item'); + o2.id = 'I2'; r = new RelationOp([o, o, o2], []); - expect(r.relationsToAdd).toEqual(["I1", "I2"]); + expect(r.relationsToAdd).toEqual(['I1', 'I2']); expect(r.relationsToRemove).toEqual([]); - expect(r._targetClassName).toBe("Item"); + expect(r._targetClassName).toBe('Item'); expect(r.toJSON()).toEqual({ - __op: "AddRelation", + __op: 'AddRelation', objects: [ - { __type: "Pointer", objectId: "I1", className: "Item" }, - { __type: "Pointer", objectId: "I2", className: "Item" }, + { __type: 'Pointer', objectId: 'I1', className: 'Item' }, + { __type: 'Pointer', objectId: 'I2', className: 'Item' }, ], }); expect(opFromJSON(r.toJSON())).toEqual(r); - const o3 = new ParseObject("Item"); - o3.id = "I3"; + const o3 = new ParseObject('Item'); + o3.id = 'I3'; const r2 = new RelationOp([], [o3, o, o]); expect(r2.relationsToAdd).toEqual([]); - expect(r2.relationsToRemove).toEqual(["I3", "I1"]); + expect(r2.relationsToRemove).toEqual(['I3', 'I1']); expect(r2.toJSON()).toEqual({ - __op: "RemoveRelation", + __op: 'RemoveRelation', objects: [ - { __type: "Pointer", objectId: "I3", className: "Item" }, - { __type: "Pointer", objectId: "I1", className: "Item" }, + { __type: 'Pointer', objectId: 'I3', className: 'Item' }, + { __type: 'Pointer', objectId: 'I1', className: 'Item' }, ], }); expect(opFromJSON(r2.toJSON())).toEqual(r2); - const rel = r.applyTo( - undefined, - { className: "Delivery", id: "D3" }, - "shipments" - ); - expect(rel.targetClassName).toBe("Item"); - expect(r2.applyTo(rel, { className: "Delivery", id: "D3" })).toBe(rel); + const rel = r.applyTo(undefined, { className: 'Delivery', id: 'D3' }, 'shipments'); + expect(rel.targetClassName).toBe('Item'); + expect(r2.applyTo(rel, { className: 'Delivery', id: 'D3' })).toBe(rel); - const relLocal = r.applyTo( - undefined, - { className: "Delivery", id: "localD4" }, - "shipments" - ); - expect(relLocal.parent._localId).toBe("localD4"); + const relLocal = r.applyTo(undefined, { className: 'Delivery', id: 'localD4' }, 'shipments'); + expect(relLocal.parent._localId).toBe('localD4'); - expect(r.applyTo.bind(r, "string")).toThrow( - "Relation cannot be applied to a non-relation field" + expect(r.applyTo.bind(r, 'string')).toThrow( + 'Relation cannot be applied to a non-relation field' ); expect(r.applyTo.bind(r)).toThrow( - "Cannot apply a RelationOp without either a previous value, or an object and a key" + 'Cannot apply a RelationOp without either a previous value, or an object and a key' ); - const p = new ParseObject("Person"); - p.id = "P4"; + 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"); + r3.applyTo(noRelation, { className: 'Delivery', id: 'D3' }, 'packages'); expect(noRelation.targetClassName).toEqual(r3._targetClassName); expect(r.mergeWith(null)).toBe(r); expect(r.mergeWith.bind(r, new UnsetOp())).toThrow( - "You cannot modify a relation after deleting it." + 'You cannot modify a relation after deleting it.' ); expect(r.mergeWith.bind(r, new SetOp(12))).toThrow( - "Cannot merge Relation Op with the previous Op" + 'Cannot merge Relation Op with the previous Op' ); const merged = r2.mergeWith(r); expect(merged.toJSON()).toEqual({ - __op: "Batch", + __op: 'Batch', ops: [ { - __op: "AddRelation", - objects: [{ __type: "Pointer", objectId: "I2", className: "Item" }], + __op: 'AddRelation', + objects: [{ __type: 'Pointer', objectId: 'I2', className: 'Item' }], }, { - __op: "RemoveRelation", + __op: 'RemoveRelation', objects: [ - { __type: "Pointer", objectId: "I3", className: "Item" }, - { __type: "Pointer", objectId: "I1", className: "Item" }, + { __type: 'Pointer', objectId: 'I3', className: 'Item' }, + { __type: 'Pointer', objectId: 'I1', className: 'Item' }, ], }, ], @@ -479,28 +455,28 @@ describe("ParseOp", () => { expect(opFromJSON(merged.toJSON())).toEqual(merged); }); - it("can merge Relation Op with the previous Op", () => { + it('can merge Relation Op with the previous Op', () => { const r = new RelationOp(); const relation = new ParseRelation(null, null); const set = new SetOp(relation); expect(r.mergeWith(set)).toEqual(r); - const a = new ParseObject("Item"); - a.id = "I1"; - const b = new ParseObject("Item"); - b.id = "D1"; + const a = new ParseObject('Item'); + a.id = 'I1'; + const b = new ParseObject('Item'); + b.id = 'D1'; const r1 = new RelationOp([a, b], []); const r2 = new RelationOp([], [b]); expect(() => { r.mergeWith(r1); - }).toThrow("Related object must be of class Item, but null was passed in."); + }).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])); }); - it("opFromJSON Relation", () => { + it('opFromJSON Relation', () => { const r = new RelationOp([], []); - expect(opFromJSON({ __op: "AddRelation", objects: "" })).toEqual(r); - expect(opFromJSON({ __op: "RemoveRelation", objects: "" })).toEqual(r); + expect(opFromJSON({ __op: 'AddRelation', objects: '' })).toEqual(r); + expect(opFromJSON({ __op: 'RemoveRelation', objects: '' })).toEqual(r); }); }); diff --git a/src/__tests__/ParsePolygon-test.js b/src/__tests__/ParsePolygon-test.js index 29503b476..ef500c0e7 100644 --- a/src/__tests__/ParsePolygon-test.js +++ b/src/__tests__/ParsePolygon-test.js @@ -1,7 +1,7 @@ jest.autoMockOff(); -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParsePolygon = require("../ParsePolygon").default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParsePolygon = require('../ParsePolygon').default; const points = [ [0, 0], @@ -11,13 +11,13 @@ const points = [ [0, 0], ]; -describe("Polygon", () => { - it("can initialize with points", () => { +describe('Polygon', () => { + it('can initialize with points', () => { const polygon = new ParsePolygon(points); expect(polygon.coordinates).toEqual(points); }); - it("can initialize with geopoints", () => { + it('can initialize with geopoints', () => { const geopoints = [ new ParseGeoPoint(0, 0), new ParseGeoPoint(0, 1), @@ -29,7 +29,7 @@ describe("Polygon", () => { expect(polygon.coordinates).toEqual(points); }); - it("can set points", () => { + it('can set points', () => { const newPoints = [ [0, 0], [0, 10], @@ -45,15 +45,15 @@ describe("Polygon", () => { expect(polygon.coordinates).toEqual(newPoints); }); - it("toJSON", () => { + it('toJSON', () => { const polygon = new ParsePolygon(points); expect(polygon.toJSON()).toEqual({ - __type: "Polygon", + __type: 'Polygon', coordinates: points, }); }); - it("equals", () => { + it('equals', () => { const polygon1 = new ParsePolygon(points); const polygon2 = new ParsePolygon(points); const geopoint = new ParseGeoPoint(0, 0); @@ -72,7 +72,7 @@ describe("Polygon", () => { expect(polygon1.equals(polygon2)).toBe(false); }); - it("containsPoint", () => { + it('containsPoint', () => { const polygon = new ParsePolygon(points); const outside = new ParseGeoPoint(10, 10); const inside = new ParseGeoPoint(0.5, 0.5); @@ -81,17 +81,17 @@ describe("Polygon", () => { expect(polygon.containsPoint(outside)).toBe(false); }); - it("throws error on invalid input", () => { + it('throws error on invalid input', () => { expect(() => { new ParsePolygon(); - }).toThrow("Coordinates must be an Array"); + }).toThrow('Coordinates must be an Array'); expect(() => { new ParsePolygon([]); - }).toThrow("Polygon must have at least 3 GeoPoints or Points"); + }).toThrow('Polygon must have at least 3 GeoPoints or Points'); expect(() => { new ParsePolygon([1, 2, 3]); - }).toThrow("Coordinates must be an Array of GeoPoints or Points"); + }).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 dc9ddca21..c5d7f86fc 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -7,21 +7,21 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../encode"); -jest.dontMock("../decode"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseQuery"); -jest.dontMock("../promiseUtils"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../UniqueInstanceStateController"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../LocalDatastore"); -jest.dontMock("../OfflineQuery"); -jest.dontMock("../LiveQuerySubscription"); - -jest.mock("uuid/v4", () => { +jest.dontMock('../CoreManager'); +jest.dontMock('../encode'); +jest.dontMock('../decode'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseQuery'); +jest.dontMock('../promiseUtils'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../LocalDatastore'); +jest.dontMock('../OfflineQuery'); +jest.dontMock('../LiveQuerySubscription'); + +jest.mock('uuid/v4', () => { let value = 0; return () => value++; }); @@ -34,26 +34,26 @@ mockObject.fromJSON = function (json) { const o = new mockObject(json.className); o.id = json.objectId; for (const attr in json) { - if (attr !== "className" && attr !== "__type" && attr !== "objectId") { + if (attr !== 'className' && attr !== '__type' && attr !== 'objectId') { o.attributes[attr] = json[attr]; } } return o; }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); const mockLocalDatastore = { _serializeObjectsFromPinName: jest.fn(), checkIfEnabled: jest.fn(), }; -jest.setMock("../LocalDatastore", mockLocalDatastore); +jest.setMock('../LocalDatastore', mockLocalDatastore); -let CoreManager = require("../CoreManager"); -const ParseError = require("../ParseError").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -let ParseObject = require("../ParseObject"); -let ParseQuery = require("../ParseQuery").default; -const LiveQuerySubscription = require("../LiveQuerySubscription").default; +let CoreManager = require('../CoreManager'); +const ParseError = require('../ParseError').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +let ParseObject = require('../ParseObject'); +let ParseQuery = require('../ParseQuery').default; +const LiveQuerySubscription = require('../LiveQuerySubscription').default; const MockRESTController = { request: jest.fn(), @@ -62,79 +62,77 @@ const MockRESTController = { const QueryController = CoreManager.getQueryController(); -import { DEFAULT_PIN } from "../LocalDatastoreUtils"; +import { DEFAULT_PIN } from '../LocalDatastoreUtils'; -describe("ParseQuery", () => { +describe('ParseQuery', () => { beforeEach(() => { CoreManager.setQueryController(QueryController); CoreManager.setRESTController(MockRESTController); }); - it("can be constructed from a class name", () => { - const q = new ParseQuery("Item"); - expect(q.className).toBe("Item"); + it('can be constructed from a class name', () => { + const q = new ParseQuery('Item'); + expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ where: {}, }); }); - it("can be constructed from a ParseObject", () => { - const item = new ParseObject("Item"); + it('can be constructed from a ParseObject', () => { + const item = new ParseObject('Item'); const q2 = new ParseQuery(item); - expect(q2.className).toBe("Item"); + expect(q2.className).toBe('Item'); expect(q2.toJSON()).toEqual({ where: {}, }); }); - it("can be constructed from a function constructor", () => { + it('can be constructed from a function constructor', () => { function ObjectFunction() { - this.className = "Item"; + this.className = 'Item'; } const q = new ParseQuery(ObjectFunction); - expect(q.className).toBe("Item"); + expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ where: {}, }); }); - it("can be constructed from a function prototype", () => { + it('can be constructed from a function prototype', () => { function ObjectFunction() {} - ObjectFunction.className = "Item"; + ObjectFunction.className = 'Item'; const q = new ParseQuery(ObjectFunction); - expect(q.className).toBe("Item"); + expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ where: {}, }); }); - it("throws when created with invalid data", () => { + it('throws when created with invalid data', () => { 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", () => { - const q = new ParseQuery("Item"); - q.equalTo("size", "medium"); + it('can generate equality queries', () => { + const q = new ParseQuery('Item'); + q.equalTo('size', 'medium'); expect(q.toJSON()).toEqual({ where: { - size: "medium", + size: 'medium', }, }); // Overrides old constraint - q.equalTo("size", "small"); + q.equalTo('size', 'small'); expect(q.toJSON()).toEqual({ where: { - size: "small", + size: 'small', }, }); // equalTo('key', undefined) resolves to 'does not exist' - q.equalTo("size"); + q.equalTo('size'); expect(q.toJSON()).toEqual({ where: { size: { @@ -143,44 +141,44 @@ describe("ParseQuery", () => { }, }); - const size = "medium"; + const size = 'medium'; const stock = true; q.equalTo({ size, stock }); expect(q.toJSON()).toEqual({ where: { - size: "medium", + size: 'medium', stock: true, }, }); }); - it("can generate inequality queries", () => { - const q = new ParseQuery("Item"); - q.notEqualTo("size", "small"); + it('can generate inequality queries', () => { + const q = new ParseQuery('Item'); + q.notEqualTo('size', 'small'); expect(q.toJSON()).toEqual({ where: { size: { - $ne: "small", + $ne: 'small', }, }, }); - q.notEqualTo("size", "medium"); + q.notEqualTo('size', 'medium'); expect(q.toJSON()).toEqual({ where: { size: { - $ne: "medium", + $ne: 'medium', }, }, }); - const size = "medium"; + const size = 'medium'; const stock = true; q.notEqualTo({ size, stock }); expect(q.toJSON()).toEqual({ where: { size: { - $ne: "medium", + $ne: 'medium', }, stock: { $ne: true, @@ -189,9 +187,9 @@ describe("ParseQuery", () => { }); }); - it("can generate less-than queries", () => { - const q = new ParseQuery("Item"); - q.lessThan("inStock", 10); + it('can generate less-than queries', () => { + const q = new ParseQuery('Item'); + q.lessThan('inStock', 10); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -200,7 +198,7 @@ describe("ParseQuery", () => { }, }); - q.lessThan("inStock", 4); + q.lessThan('inStock', 4); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -210,9 +208,9 @@ describe("ParseQuery", () => { }); }); - it("can generate less-than-or-equal-to queries", () => { - const q = new ParseQuery("Item"); - q.lessThanOrEqualTo("inStock", 10); + it('can generate less-than-or-equal-to queries', () => { + const q = new ParseQuery('Item'); + q.lessThanOrEqualTo('inStock', 10); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -221,7 +219,7 @@ describe("ParseQuery", () => { }, }); - q.lessThanOrEqualTo("inStock", 4); + q.lessThanOrEqualTo('inStock', 4); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -231,9 +229,9 @@ describe("ParseQuery", () => { }); }); - it("can generate greater-than queries", () => { - const q = new ParseQuery("Item"); - q.greaterThan("inStock", 0); + it('can generate greater-than queries', () => { + const q = new ParseQuery('Item'); + q.greaterThan('inStock', 0); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -242,7 +240,7 @@ describe("ParseQuery", () => { }, }); - q.greaterThan("inStock", 100); + q.greaterThan('inStock', 100); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -252,9 +250,9 @@ describe("ParseQuery", () => { }); }); - it("can generate greater-than-or-equal-to queries", () => { - const q = new ParseQuery("Item"); - q.greaterThanOrEqualTo("inStock", 0); + it('can generate greater-than-or-equal-to queries', () => { + const q = new ParseQuery('Item'); + q.greaterThanOrEqualTo('inStock', 0); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -263,7 +261,7 @@ describe("ParseQuery", () => { }, }); - q.greaterThanOrEqualTo("inStock", 100); + q.greaterThanOrEqualTo('inStock', 100); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -273,123 +271,123 @@ describe("ParseQuery", () => { }); }); - it("can generate contained-in queries", () => { - const q = new ParseQuery("Item"); - q.containedIn("size", ["small", "medium"]); + it('can generate contained-in queries', () => { + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']); expect(q.toJSON()).toEqual({ where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, }, }); - q.containedIn("size", ["small", "medium", "large"]); + q.containedIn('size', ['small', 'medium', 'large']); expect(q.toJSON()).toEqual({ where: { size: { - $in: ["small", "medium", "large"], + $in: ['small', 'medium', 'large'], }, }, }); }); - it("can generate not-contained-in queries", () => { - const q = new ParseQuery("Item"); - q.notContainedIn("size", ["small", "medium"]); + it('can generate not-contained-in queries', () => { + const q = new ParseQuery('Item'); + q.notContainedIn('size', ['small', 'medium']); expect(q.toJSON()).toEqual({ where: { size: { - $nin: ["small", "medium"], + $nin: ['small', 'medium'], }, }, }); - q.notContainedIn("size", ["small", "large"]); + q.notContainedIn('size', ['small', 'large']); expect(q.toJSON()).toEqual({ where: { size: { - $nin: ["small", "large"], + $nin: ['small', 'large'], }, }, }); }); - it("can generate contains-all queries", () => { - const q = new ParseQuery("Item"); - q.containsAll("tags", ["hot", "sold-out"]); + it('can generate contains-all queries', () => { + const q = new ParseQuery('Item'); + q.containsAll('tags', ['hot', 'sold-out']); expect(q.toJSON()).toEqual({ where: { tags: { - $all: ["hot", "sold-out"], + $all: ['hot', 'sold-out'], }, }, }); - q.containsAll("tags", ["sale", "new"]); + q.containsAll('tags', ['sale', 'new']); expect(q.toJSON()).toEqual({ where: { tags: { - $all: ["sale", "new"], + $all: ['sale', 'new'], }, }, }); }); - it("can generate containedBy queries", () => { - const q = new ParseQuery("Item"); - q.containedBy("tags", ["hot", "sold-out"]); + it('can generate containedBy queries', () => { + const q = new ParseQuery('Item'); + q.containedBy('tags', ['hot', 'sold-out']); expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ["hot", "sold-out"], + $containedBy: ['hot', 'sold-out'], }, }, }); - q.containedBy("tags", ["sale", "new"]); + q.containedBy('tags', ['sale', 'new']); expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ["sale", "new"], + $containedBy: ['sale', 'new'], }, }, }); }); - it("can generate contains-all-starting-with queries", () => { - const q = new ParseQuery("Item"); - q.containsAllStartingWith("tags", ["ho", "out"]); + it('can generate contains-all-starting-with queries', () => { + const q = new ParseQuery('Item'); + q.containsAllStartingWith('tags', ['ho', 'out']); 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"]); + 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"); + q.containsAllStartingWith('tags', 'noArray'); expect(q.toJSON()).toEqual({ where: { tags: { - $all: [{ $regex: "^\\QnoArray\\E" }], + $all: [{ $regex: '^\\QnoArray\\E' }], }, }, }); }); - it("can generate exists queries", () => { - const q = new ParseQuery("Item"); - q.exists("name"); + it('can generate exists queries', () => { + const q = new ParseQuery('Item'); + q.exists('name'); expect(q.toJSON()).toEqual({ where: { name: { @@ -399,9 +397,9 @@ describe("ParseQuery", () => { }); }); - it("can generate does-not-exist queries", () => { - const q = new ParseQuery("Item"); - q.doesNotExist("name"); + it('can generate does-not-exist queries', () => { + const q = new ParseQuery('Item'); + q.doesNotExist('name'); expect(q.toJSON()).toEqual({ where: { name: { @@ -411,59 +409,59 @@ describe("ParseQuery", () => { }); }); - it("can generate RegExp queries", () => { - const q = new ParseQuery("Item"); - q.matches("name", /ing$/); + it('can generate RegExp queries', () => { + const q = new ParseQuery('Item'); + q.matches('name', /ing$/); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "ing$", + $regex: 'ing$', }, }, }); - q.matches("name", /\bor\b/, "i"); + q.matches('name', /\bor\b/, 'i'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\bor\\b", - $options: "i", + $regex: '\\bor\\b', + $options: 'i', }, }, }); - q.matches("name", /\bor\b/i); + q.matches('name', /\bor\b/i); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\bor\\b", - $options: "i", + $regex: '\\bor\\b', + $options: 'i', }, }, }); - q.matches("name", /\bor\b/im); + q.matches('name', /\bor\b/im); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\bor\\b", - $options: "im", + $regex: '\\bor\\b', + $options: 'im', }, }, }); }); - it("can generate queries that match results from other queries", () => { - const q1 = new ParseQuery("Item"); - q1.equalTo("inStock", 0); + it('can generate queries that match results from other queries', () => { + const q1 = new ParseQuery('Item'); + q1.equalTo('inStock', 0); - const q2 = new ParseQuery("Purchase"); - q2.matchesQuery("item", q1); + const q2 = new ParseQuery('Purchase'); + q2.matchesQuery('item', q1); expect(q2.toJSON()).toEqual({ where: { item: { $inQuery: { - className: "Item", + className: 'Item', where: { inStock: 0, }, @@ -474,16 +472,16 @@ describe("ParseQuery", () => { }); it("can generate queries that don't match results from other queries", () => { - const q1 = new ParseQuery("Item"); - q1.equalTo("inStock", 0); + const q1 = new ParseQuery('Item'); + q1.equalTo('inStock', 0); - const q2 = new ParseQuery("Purchase"); - q2.doesNotMatchQuery("item", q1); + const q2 = new ParseQuery('Purchase'); + q2.doesNotMatchQuery('item', q1); expect(q2.toJSON()).toEqual({ where: { item: { $notInQuery: { - className: "Item", + className: 'Item', where: { inStock: 0, }, @@ -493,19 +491,19 @@ describe("ParseQuery", () => { }); }); - it("can generate queries that match keys from other queries", () => { - const q1 = new ParseQuery("Item"); - q1.equalTo("inStock", 0); + it('can generate queries that match keys from other queries', () => { + const q1 = new ParseQuery('Item'); + q1.equalTo('inStock', 0); - const q2 = new ParseQuery("Review"); - q2.matchesKeyInQuery("itemName", "name", q1); + const q2 = new ParseQuery('Review'); + q2.matchesKeyInQuery('itemName', 'name', q1); expect(q2.toJSON()).toEqual({ where: { itemName: { $select: { - key: "name", + key: 'name', query: { - className: "Item", + className: 'Item', where: { inStock: 0, }, @@ -517,18 +515,18 @@ describe("ParseQuery", () => { }); it("can generate queries that don't match keys from other queries", () => { - const q1 = new ParseQuery("Item"); - q1.equalTo("inStock", 0); + const q1 = new ParseQuery('Item'); + q1.equalTo('inStock', 0); - const q2 = new ParseQuery("Review"); - q2.doesNotMatchKeyInQuery("itemName", "name", q1); + const q2 = new ParseQuery('Review'); + q2.doesNotMatchKeyInQuery('itemName', 'name', q1); expect(q2.toJSON()).toEqual({ where: { itemName: { $dontSelect: { - key: "name", + key: 'name', query: { - className: "Item", + className: 'Item', where: { inStock: 0, }, @@ -539,99 +537,99 @@ describe("ParseQuery", () => { }); }); - it("can generate string-contains queries", () => { - const q = new ParseQuery("Item"); - expect(q.contains.bind(q, "name", 12)).toThrow( - "The value being searched for must be a string." + it('can generate string-contains queries', () => { + const q = new ParseQuery('Item'); + expect(q.contains.bind(q, 'name', 12)).toThrow( + 'The value being searched for must be a string.' ); - q.contains("name", " or "); + q.contains('name', ' or '); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\Q or \\E", + $regex: '\\Q or \\E', }, }, }); // Test escaping in quote() - q.contains("name", "slash-E \\E"); + q.contains('name', 'slash-E \\E'); 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"); + q.contains('name', 'slash-Q \\Q'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\Qslash-Q \\Q\\E", + $regex: '\\Qslash-Q \\Q\\E', }, }, }); }); - it("can generate string-starts-with queries", () => { - const q = new ParseQuery("Item"); - expect(q.startsWith.bind(q, "name", 12)).toThrow( - "The value being searched for must be a string." + it('can generate string-starts-with queries', () => { + const q = new ParseQuery('Item'); + expect(q.startsWith.bind(q, 'name', 12)).toThrow( + 'The value being searched for must be a string.' ); - q.startsWith("name", "Abc"); + q.startsWith('name', 'Abc'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "^\\QAbc\\E", + $regex: '^\\QAbc\\E', }, }, }); - q.startsWith("name", "Def"); + q.startsWith('name', 'Def'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "^\\QDef\\E", + $regex: '^\\QDef\\E', }, }, }); }); - it("can generate string-ends-with queries", () => { - const q = new ParseQuery("Item"); - expect(q.endsWith.bind(q, "name", 12)).toThrow( - "The value being searched for must be a string." + it('can generate string-ends-with queries', () => { + const q = new ParseQuery('Item'); + expect(q.endsWith.bind(q, 'name', 12)).toThrow( + 'The value being searched for must be a string.' ); - q.endsWith("name", "XYZ"); + q.endsWith('name', 'XYZ'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\QXYZ\\E$", + $regex: '\\QXYZ\\E$', }, }, }); - q.endsWith("name", "xyz"); + q.endsWith('name', 'xyz'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: "\\Qxyz\\E$", + $regex: '\\Qxyz\\E$', }, }, }); }); - it("can generate near-geopoint queries", () => { - const q = new ParseQuery("Shipment"); - q.near("shippedTo", new ParseGeoPoint(10, 20)); + it('can generate near-geopoint queries', () => { + const q = new ParseQuery('Shipment'); + q.near('shippedTo', new ParseGeoPoint(10, 20)); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 10, longitude: 20, }, @@ -639,12 +637,12 @@ describe("ParseQuery", () => { }, }); - q.near("shippedTo", [30, 40]); + q.near('shippedTo', [30, 40]); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 30, longitude: 40, }, @@ -653,12 +651,12 @@ describe("ParseQuery", () => { }); // GeoPoint's internal fallback - q.near("shippedTo", "string"); + q.near('shippedTo', 'string'); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 0, longitude: 0, }, @@ -667,14 +665,14 @@ describe("ParseQuery", () => { }); }); - it("can generate near-geopoint queries with ranges", () => { - const q = new ParseQuery("Shipment"); - q.withinRadians("shippedTo", [20, 40], 2, true); + it('can generate near-geopoint queries with ranges', () => { + const q = new ParseQuery('Shipment'); + q.withinRadians('shippedTo', [20, 40], 2, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20, longitude: 40, }, @@ -683,12 +681,12 @@ describe("ParseQuery", () => { }, }); - q.withinMiles("shippedTo", [20, 30], 3958.8, true); + q.withinMiles('shippedTo', [20, 30], 3958.8, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20, longitude: 30, }, @@ -697,12 +695,12 @@ describe("ParseQuery", () => { }, }); - q.withinKilometers("shippedTo", [30, 30], 6371.0, true); + q.withinKilometers('shippedTo', [30, 30], 6371.0, true); expect(q.toJSON()).toEqual({ where: { shippedTo: { $nearSphere: { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 30, longitude: 30, }, @@ -712,9 +710,9 @@ describe("ParseQuery", () => { }); }); - it("can generate near-geopoint queries without sorting", () => { - const q = new ParseQuery("Shipment"); - q.withinRadians("shippedTo", new ParseGeoPoint(20, 40), 2, false); + it('can generate near-geopoint queries without sorting', () => { + const q = new ParseQuery('Shipment'); + q.withinRadians('shippedTo', new ParseGeoPoint(20, 40), 2, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { @@ -728,7 +726,7 @@ describe("ParseQuery", () => { }, }); - q.withinMiles("shippedTo", new ParseGeoPoint(20, 30), 3958.8, false); + q.withinMiles('shippedTo', new ParseGeoPoint(20, 30), 3958.8, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { @@ -742,7 +740,7 @@ describe("ParseQuery", () => { }, }); - q.withinKilometers("shippedTo", new ParseGeoPoint(30, 30), 6371.0, false); + q.withinKilometers('shippedTo', new ParseGeoPoint(30, 30), 6371.0, false); expect(q.toJSON()).toEqual({ where: { shippedTo: { @@ -757,21 +755,21 @@ describe("ParseQuery", () => { }); }); - it("can generate geobox queries", () => { - const q = new ParseQuery("Shipment"); - q.withinGeoBox("shippedTo", [20, 20], [10, 30]); + it('can generate geobox queries', () => { + const q = new ParseQuery('Shipment'); + q.withinGeoBox('shippedTo', [20, 20], [10, 30]); expect(q.toJSON()).toEqual({ where: { shippedTo: { $within: { $box: [ { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20, longitude: 20, }, { - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 10, longitude: 30, }, @@ -782,10 +780,10 @@ describe("ParseQuery", () => { }); }); - it("can combine multiple clauses", () => { - const q = new ParseQuery("Item"); - q.lessThan("inStock", 10); - q.greaterThan("inStock", 0); + it('can combine multiple clauses', () => { + const q = new ParseQuery('Item'); + q.lessThan('inStock', 10); + q.greaterThan('inStock', 0); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -795,7 +793,7 @@ describe("ParseQuery", () => { }, }); - q.containedIn("size", ["small", "medium"]); + q.containedIn('size', ['small', 'medium']); expect(q.toJSON()).toEqual({ where: { inStock: { @@ -803,170 +801,164 @@ describe("ParseQuery", () => { $gt: 0, }, size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, }, }); }); - it("can specify ordering", () => { - const q = new ParseQuery("Item"); - q.greaterThan("inStock", 0).ascending("createdAt"); + it('can specify ordering', () => { + const q = new ParseQuery('Item'); + q.greaterThan('inStock', 0).ascending('createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "createdAt", + order: 'createdAt', }); // overrides - q.ascending("name"); + q.ascending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "name", + order: 'name', }); - q.ascending("name"); + q.ascending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "name", + order: 'name', }); // removes whitespace - q.ascending(" createdAt"); + q.ascending(' createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "createdAt", + order: 'createdAt', }); // add additional ordering - q.addAscending("name"); + q.addAscending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "createdAt,name", + order: 'createdAt,name', }); - q.ascending(["a", "b", "c"]); + q.ascending(['a', 'b', 'c']); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "a,b,c", + order: 'a,b,c', }); - q.ascending("name", "createdAt"); + q.ascending('name', 'createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "name,createdAt", + order: 'name,createdAt', }); - q.descending("createdAt"); + q.descending('createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "-createdAt", + order: '-createdAt', }); - q.addAscending("name"); + q.addAscending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "-createdAt,name", + order: '-createdAt,name', }); - q.addDescending("a", "b", "c"); + q.addDescending('a', 'b', 'c'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "-createdAt,name,-a,-b,-c", + order: '-createdAt,name,-a,-b,-c', }); - q.descending(["a", "b"]); + q.descending(['a', 'b']); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - order: "-a,-b", + order: '-a,-b', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.addDescending(); expect(q2.toJSON()).toEqual({ where: {}, - order: "", + order: '', }); - const q3 = new ParseQuery("Item"); + const q3 = new ParseQuery('Item'); q3.addAscending(); expect(q3.toJSON()).toEqual({ where: {}, - order: "", + order: '', }); }); - 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" - ); + 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'); q.skip(4); expect(q.toJSON()).toEqual({ where: {}, skip: 4, }); - q.equalTo("name", "Product 5"); + q.equalTo('name', 'Product 5'); expect(q.toJSON()).toEqual({ where: { - name: "Product 5", + name: 'Product 5', }, 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" - ); + 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'); q.limit(10); expect(q.toJSON()).toEqual({ @@ -979,11 +971,9 @@ describe("ParseQuery", () => { }); }); - 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" - ); + 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'); q.withCount(true); expect(q.toJSON()).toEqual({ @@ -996,24 +986,24 @@ describe("ParseQuery", () => { }); }); - it("can set hint value", () => { - const q = new ParseQuery("Item"); - q.hint("_id_"); + it('can set hint value', () => { + const q = new ParseQuery('Item'); + q.hint('_id_'); expect(q.toJSON()).toEqual({ where: {}, - hint: "_id_", + hint: '_id_', }); }); - it("can set explain value", () => { - const q = new ParseQuery("Item"); + it('can set explain value', () => { + const q = new ParseQuery('Item'); q.explain(); const json = q.toJSON(); expect(json).toEqual({ where: {}, explain: true, }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); expect(q2._explain).toBe(true); @@ -1021,147 +1011,142 @@ describe("ParseQuery", () => { expect(q.toJSON()).toEqual({ where: {}, }); - expect(q.explain.bind(q, "not boolean")).toThrow( - "You can only set explain to a boolean value" - ); + expect(q.explain.bind(q, 'not boolean')).toThrow('You can only set explain to a boolean value'); }); - it("can generate queries that include full data for pointers", () => { - const q = new ParseQuery("Item"); - q.greaterThan("inStock", 0); - q.include("manufacturer"); + it('can generate queries that include full data for pointers', () => { + const q = new ParseQuery('Item'); + q.greaterThan('inStock', 0); + q.include('manufacturer'); expect(q.toJSON()).toEqual({ where: { inStock: { $gt: 0, }, }, - include: "manufacturer", + include: 'manufacturer', }); - q.include("previousModel", "nextModel"); + q.include('previousModel', 'nextModel'); expect(q.toJSON()).toEqual({ where: { inStock: { $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, }, }, - include: - "manufacturer,previousModel,nextModel,lastPurchaser,lastPurchase", + include: 'manufacturer,previousModel,nextModel,lastPurchaser,lastPurchase', }); }); - it("can includeAll for pointers", () => { - const q = new ParseQuery("Item"); + it('can includeAll for pointers', () => { + const q = new ParseQuery('Item'); q.includeAll(); const json = q.toJSON(); expect(json).toEqual({ where: {}, - include: "*", + include: '*', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); - expect(q2._include).toEqual(["*"]); + expect(q2._include).toEqual(['*']); }); - it("can exclude keys", () => { - const q = new ParseQuery("Item"); - q.exclude("foo"); + it('can exclude keys', () => { + const q = new ParseQuery('Item'); + q.exclude('foo'); const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: "foo", + excludeKeys: 'foo', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); - expect(q2._exclude).toEqual(["foo"]); + expect(q2._exclude).toEqual(['foo']); }); - it("can exclude multiple keys", () => { - const q = new ParseQuery("Item"); - q.exclude(["foo", "bar"]); + it('can exclude multiple keys', () => { + const q = new ParseQuery('Item'); + q.exclude(['foo', 'bar']); const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: "foo,bar", + excludeKeys: 'foo,bar', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); - expect(q2._exclude).toEqual(["foo", "bar"]); + expect(q2._exclude).toEqual(['foo', 'bar']); }); - it("can use extraOptions", () => { - const q = new ParseQuery("Item"); - q._extraOptions.randomOption = "test"; + it('can use extraOptions', () => { + const q = new ParseQuery('Item'); + q._extraOptions.randomOption = 'test'; const json = q.toJSON(); expect(json).toEqual({ where: {}, - randomOption: "test", + randomOption: 'test', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); - expect(q2._extraOptions.randomOption).toBe("test"); + expect(q2._extraOptions.randomOption).toBe('test'); }); - it("can use hint", () => { - const q = new ParseQuery("Item"); - q.hint("_id_"); + it('can use hint', () => { + const q = new ParseQuery('Item'); + q.hint('_id_'); const json = q.toJSON(); expect(json).toEqual({ where: {}, - hint: "_id_", + hint: '_id_', }); - const q2 = new ParseQuery("Item"); + const q2 = new ParseQuery('Item'); q2.withJSON(json); - expect(q2._hint).toBe("_id_"); + expect(q2._hint).toBe('_id_'); }); - it("can specify certain fields to send back", () => { - const q = new ParseQuery("Item"); - q.select("size"); + it('can specify certain fields to send back', () => { + const q = new ParseQuery('Item'); + q.select('size'); expect(q.toJSON()).toEqual({ where: {}, - keys: "size", + keys: 'size', }); - q.select("inStock", "lastPurchase"); + 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." - ); + 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.'); - q2 = new ParseQuery("Item"); - q.equalTo("size", "medium"); - q2.equalTo("size", "large"); + q2 = new ParseQuery('Item'); + q.equalTo('size', 'medium'); + q2.equalTo('size', 'large'); let mediumOrLarge = ParseQuery.or(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $or: [{ size: "medium" }, { size: "large" }], + $or: [{ size: 'medium' }, { size: 'large' }], }, }); @@ -1170,26 +1155,24 @@ 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." - ); + 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.'); - q2 = new ParseQuery("Item"); - q.equalTo("size", "medium"); - q2.equalTo("size", "large"); + q2 = new ParseQuery('Item'); + q.equalTo('size', 'medium'); + q2.equalTo('size', 'large'); let mediumOrLarge = ParseQuery.and(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $and: [{ size: "medium" }, { size: "large" }], + $and: [{ size: 'medium' }, { size: 'large' }], }, }); @@ -1198,26 +1181,24 @@ 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." - ); + 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.'); - q2 = new ParseQuery("Item"); - q.equalTo("size", "medium"); - q2.equalTo("size", "large"); + q2 = new ParseQuery('Item'); + q.equalTo('size', 'medium'); + q2.equalTo('size', 'large'); let mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [{ size: "medium" }, { size: "large" }], + $nor: [{ size: 'medium' }, { size: 'large' }], }, }); @@ -1226,149 +1207,149 @@ 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); 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") + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') .first() - .then((obj) => { + .then(obj => { expect(obj instanceof ParseObject).toBe(true); - expect(obj.className).toBe("Item"); - expect(obj.id).toBe("I1"); + expect(obj.className).toBe('Item'); + expect(obj.id).toBe('I1'); expect(obj.attributes).toEqual({ - size: "small", - name: "Product 3", + size: 'small', + name: 'Product 3', }); 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 1, where: { - size: "small", + size: 'small', }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [], }); }, }); - const q = new ParseQuery("Item"); - q.equalTo("size", "small") + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') .first({ useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', }) - .then((obj) => { + .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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); 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", + objectId: 'I1', + size: 'small', + name: 'Product 3', }, }); }, }); - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); q.explain(); - q.equalTo("size", "small") + q.equalTo('size', 'small') .find() - .then((result) => { - expect(result.objectId).toBe("I1"); - expect(result.size).toBe("small"); - expect(result.name).toEqual("Product 3"); + .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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); 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) => { + const q = new ParseQuery('Item'); + q.get('I27').then(obj => { expect(obj instanceof ParseObject).toBe(true); - expect(obj.className).toBe("Item"); - expect(obj.id).toBe("I27"); + expect(obj.className).toBe('Item'); + expect(obj.id).toBe('I27'); expect(obj.attributes).toEqual({ - size: "large", - name: "Product 27", + size: 'large', + 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 1, where: { - objectId: "I28", + objectId: 'I28', }, }); expect(options.requestTask).toBeDefined(); @@ -1378,62 +1359,62 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.get("I28").then( + const q = new ParseQuery('Item'); + q.get('I28').then( () => { // Should not be reached expect(true).toBe(false); done(); }, - (err) => { + err => { expect(err.code).toBe(ParseError.OBJECT_NOT_FOUND); - expect(err.message).toBe("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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 1, where: { - objectId: "I27", + objectId: 'I27', }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + 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", { + const q = new ParseQuery('Item'); + q.get('I27', { useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 0, count: 1, where: { - size: "small", + size: 'small', }, }); expect(options.requestTask).toBeDefined(); @@ -1444,29 +1425,29 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.equalTo("size", "small") + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') .count() - .then((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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 0, count: 1, where: { - size: "small", + size: 'small', }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [], count: 145, @@ -1474,86 +1455,86 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.equalTo("size", "small") + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') .count({ useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', }) - .then((count) => { + .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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 2, skip: 8, - keys: "size,name", - order: "createdAt", + keys: 'size,name', + order: 'createdAt', where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, }, - readPreference: "PRIMARY", - includeReadPreference: "SECONDARY", - subqueryReadPreference: "SECONDARY_PREFERRED", + readPreference: 'PRIMARY', + includeReadPreference: 'SECONDARY', + subqueryReadPreference: 'SECONDARY_PREFERRED', }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, + { objectId: 'I55', size: 'medium', name: 'Product 55' }, + { objectId: 'I89', size: 'small', name: 'Product 89' }, ], }); }, }); - const q = new ParseQuery("Item"); - q.containedIn("size", ["small", "medium"]) + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']) .limit(2) .skip(8) - .ascending("createdAt") - .select("size", "name") - .readPreference("PRIMARY", "SECONDARY", "SECONDARY_PREFERRED") + .ascending('createdAt') + .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", + size: 'medium', + name: 'Product 55', }); expect(objs[1] instanceof ParseObject).toBe(true); expect(objs[1].attributes).toEqual({ - size: "small", - name: "Product 89", + size: 'small', + 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); expect(options.context).toEqual(context); return Promise.resolve({ results: [], @@ -1561,70 +1542,70 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.containedIn("size", ["small", "medium"]) + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']) .find({ useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', 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(className).toBe('Item'); expect(params).toEqual({ where: {}, count: 1, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [ - { objectId: "1", name: "Product 55" }, - { objectId: "2", name: "Product 89" }, + { objectId: '1', name: 'Product 55' }, + { objectId: '2', name: 'Product 89' }, ], count: 2, }); }, }); - const q = new ParseQuery("Item"); + 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(); - expect(typeof obj.count).toBe("number"); + expect(typeof obj.count).toBe('number'); done(); }); }); - describe("iterating over batches with .eachBatch()", () => { + describe('iterating over batches with .eachBatch()', () => { 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" }, + { 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" }], + results: [{ objectId: 'I91', size: 'small', name: 'Product 91' }], }) ); CoreManager.setQueryController({ @@ -1633,41 +1614,37 @@ 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.equalTo("valid", true); - q.equalTo("arrayField", ["a", "b"]); - q.select("size", "name"); + 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.equalTo('valid', true); + q.equalTo('arrayField', ['a', 'b']); + q.select('size', 'name'); q.includeAll(); - q.hint("_id_"); + q.hint('_id_'); await q.eachBatch(() => {}); 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", - keys: "size,name", - include: "*", - hint: "_id_", + order: 'objectId', + keys: 'size,name', + include: '*', + hint: '_id_', where: { - arrayField: ["a", "b"], + arrayField: ['a', 'b'], size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, name: { $select: { - key: "productName", + key: 'productName', query: { - className: "Review", + className: 'Review', where: { stars: 5, }, @@ -1680,84 +1657,84 @@ describe("ParseQuery", () => { expect(options.requestTask).toBeDefined(); }); - it("passes options through to the REST API", async () => { + it('passes options through to the REST API', async () => { const batchOptions = { useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', batchSize: 50, }; - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); await q.eachBatch(() => {}, batchOptions); expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 50, - order: "objectId", + order: 'objectId', where: {}, }); expect(options.useMasterKey).toBe(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); }); - it("only makes one request when the results fit in one page", async () => { - const q = new ParseQuery("Item"); + it('only makes one request when the results fit in one page', async () => { + const q = new ParseQuery('Item'); await q.eachBatch(() => {}); expect(findMock).toHaveBeenCalledTimes(1); }); - it("makes more requests when the results do not fit in one page", async () => { - const q = new ParseQuery("Item"); + it('makes more requests when the results do not fit in one page', async () => { + 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 () => { + it('stops iteration when the callback returns a promise that rejects', async () => { let callCount = 0; const callback = () => { callCount++; - return Promise.reject(new Error("Callback rejecting")); + return Promise.reject(new Error('Callback rejecting')); }; - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); await q.eachBatch(callback, { batchSize: 2 }).catch(() => {}); expect(callCount).toBe(1); }); - it("handles a synchronous callback", async () => { + 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)); + const q = new ParseQuery('Item'); + await q.eachBatch(items => { + items.map(item => results.push(item.attributes.size)); }); - expect(results).toEqual(["medium", "small"]); + expect(results).toEqual(['medium', 'small']); }); - it("handles an asynchronous callback", async () => { + 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)); - return new Promise((resolve) => setImmediate(resolve)); + const q = new ParseQuery('Item'); + await q.eachBatch(items => { + items.map(item => results.push(item.attributes.size)); + return new Promise(resolve => setImmediate(resolve)); }); - expect(results).toEqual(["medium", "small"]); + expect(results).toEqual(['medium', 'small']); }); }); - describe("return all objects with .findAll()", () => { + describe('return all objects with .findAll()', () => { 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" }, + { 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" }], + results: [{ objectId: 'I91', size: 'small', name: 'Product 91' }], }) ); CoreManager.setQueryController({ @@ -1766,38 +1743,34 @@ 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.equalTo("valid", true); - q.select("size", "name"); + 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.equalTo('valid', true); + q.select('size', 'name'); q.includeAll(); - q.hint("_id_"); + q.hint('_id_'); 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", - keys: "size,name", - include: "*", - hint: "_id_", + order: 'objectId', + keys: 'size,name', + include: '*', + hint: '_id_', where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, name: { $select: { - key: "productName", + key: 'productName', query: { - className: "Review", + className: 'Review', where: { stars: 5, }, @@ -1810,67 +1783,64 @@ describe("ParseQuery", () => { expect(options.requestTask).toBeDefined(); }); - it("passes options through to the REST API", async () => { + it('passes options through to the REST API', async () => { const batchOptions = { useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', batchSize: 50, }; - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); await q.findAll(batchOptions); expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 50, - order: "objectId", + order: 'objectId', where: {}, }); expect(options.useMasterKey).toBe(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); }); - it("only makes one request when the results fit in one page", async () => { - const q = new ParseQuery("Item"); + it('only makes one request when the results fit in one page', async () => { + const q = new ParseQuery('Item'); await q.findAll(); expect(findMock).toHaveBeenCalledTimes(1); }); - it("makes more requests when the results do not fit in one page", async () => { - const q = new ParseQuery("Item"); + it('makes more requests when the results do not fit in one page', async () => { + const q = new ParseQuery('Item'); await q.findAll({ batchSize: 2 }); expect(findMock).toHaveBeenCalledTimes(2); }); - it("Returns all objects", async () => { - const q = new ParseQuery("Item"); + it('Returns all objects', async () => { + const q = new ParseQuery('Item'); const results = await q.findAll(); - expect(results.map((obj) => obj.attributes.size)).toEqual([ - "medium", - "small", - ]); + expect(results.map(obj => obj.attributes.size)).toEqual(['medium', 'small']); }); }); - it("can iterate over results with each()", (done) => { + it('can iterate over results with each()', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 100, - order: "objectId", - keys: "size,name", - include: "*", + order: 'objectId', + keys: 'size,name', + include: '*', where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, name: { $select: { - key: "productName", + key: 'productName', query: { - className: "Review", + className: 'Review', where: { stars: 5, }, @@ -1883,23 +1853,19 @@ describe("ParseQuery", () => { expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, - { objectId: "I91", size: "small", name: "Product 91" }, + { 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.equalTo("valid", true); - q.select("size", "name"); + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']); + q.matchesKeyInQuery('name', 'productName', new ParseQuery('Review').equalTo('stars', 5)); + q.equalTo('valid', true); + q.select('size', 'name'); q.includeAll(); let calls = 0; @@ -1911,40 +1877,40 @@ 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 100, - order: "objectId", - keys: "size,name", + order: 'objectId', + keys: 'size,name', where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, valid: true, }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); expect(options.context).toEqual(context); return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, - { objectId: "I91", size: "small", name: "Product 91" }, + { 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.equalTo("valid", true); - q.select("size", "name"); + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']); + q.equalTo('valid', true); + q.select('size', 'name'); let calls = 0; q.each( @@ -1953,7 +1919,7 @@ describe("ParseQuery", () => { }, { useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', context: context, } ).then(() => { @@ -1962,42 +1928,42 @@ describe("ParseQuery", () => { }); }); - 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ limit: 100, - order: "objectId", - keys: "size,name", + order: 'objectId', + keys: 'size,name', where: { size: { - $in: ["small", "medium"], + $in: ['small', 'medium'], }, valid: true, }, - hint: "_id_", + hint: '_id_', }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); expect(options.context).toEqual(context); return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, - { objectId: "I91", size: "small", name: "Product 91" }, + { 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.equalTo("valid", true); - q.select("size", "name"); - q.hint("_id_"); + const q = new ParseQuery('Item'); + q.containedIn('size', ['small', 'medium']); + q.equalTo('valid', true); + q.select('size', 'name'); + q.hint('_id_'); let calls = 0; q.each( @@ -2006,7 +1972,7 @@ describe("ParseQuery", () => { }, { useMasterKey: true, - sessionToken: "1234", + sessionToken: '1234', context: context, } ).then(() => { @@ -2015,126 +1981,124 @@ describe("ParseQuery", () => { }); }); - it("should add hint as string", () => { - const q = new ParseQuery("Item"); - q.hint("_id_"); - expect(q._hint).toBe("_id_"); + it('should add hint as string', () => { + const q = new ParseQuery('Item'); + q.hint('_id_'); + expect(q._hint).toBe('_id_'); }); - it("should set hint as object", () => { - const q = new ParseQuery("Item"); + it('should set hint as object', () => { + const q = new ParseQuery('Item'); q.hint({ _id: 1 }); expect(q._hint).toStrictEqual({ _id: 1 }); }); - it("should delete hint when set as undefined", () => { - const q = new ParseQuery("Item"); - q.hint("_id_"); - expect(q._hint).toBe("_id_"); + it('should delete hint when set as undefined', () => { + const q = new ParseQuery('Item'); + q.hint('_id_'); + expect(q._hint).toBe('_id_'); q.hint(); expect(q._hint).toBeUndefined(); }); - describe("iterating over results via .map()", () => { + describe('iterating over results via .map()', () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, - { objectId: "I91", size: "small", name: "Product 91" }, + { 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 q = new ParseQuery("Item"); + it('can iterate with a synchronous callback', async () => { + const callback = object => object.attributes.size; + const q = new ParseQuery('Item'); const results = await q.map(callback); - expect(results).toEqual(["medium", "small", "small"]); + expect(results).toEqual(['medium', 'small', 'small']); }); - it("can iterate with an asynchronous callback", async () => { - const callback = async (object) => object.attributes.size; - const q = new ParseQuery("Item"); + it('can iterate with an asynchronous callback', async () => { + const callback = async object => object.attributes.size; + const q = new ParseQuery('Item'); const results = await q.map(callback); - expect(results).toEqual(["medium", "small", "small"]); + expect(results).toEqual(['medium', 'small', 'small']); }); - it("stops iteration when a rejected promise is returned", async () => { + it('stops iteration when a rejected promise is returned', async () => { let callCount = 0; - await new ParseQuery("Item") + await new ParseQuery('Item') .map(() => { callCount++; - return Promise.reject(new Error("Callback rejecting")); + return Promise.reject(new Error('Callback rejecting')); }) .catch(() => {}); expect(callCount).toEqual(1); }); }); - describe("iterating over results with .reduce()", () => { + describe('iterating over results with .reduce()', () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: "I55", number: 1 }, - { objectId: "I89", number: 2 }, - { objectId: "I91", number: 3 }, + { objectId: 'I55', number: 1 }, + { objectId: 'I89', number: 2 }, + { objectId: 'I91', number: 3 }, ], }); }, }); }); - it("can iterate with a synchronous callback", async () => { - const callback = (accumulator, object) => - accumulator + object.attributes.number; - const q = new ParseQuery("Item"); + it('can iterate with a synchronous callback', async () => { + const callback = (accumulator, object) => accumulator + object.attributes.number; + const q = new ParseQuery('Item'); const result = await q.reduce(callback, 0); expect(result).toBe(6); }); - it("can iterate with an asynchronous callback", async () => { - const callback = async (accumulator, object) => - accumulator + object.attributes.number; - const q = new ParseQuery("Item"); + it('can iterate with an asynchronous callback', async () => { + const callback = async (accumulator, object) => accumulator + object.attributes.number; + const q = new ParseQuery('Item'); const result = await q.reduce(callback, 0); expect(result).toBe(6); }); - it("stops iteration when a rejected promise is returned", async () => { + it('stops iteration when a rejected promise is returned', async () => { 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"); + const q = new ParseQuery('Item'); await q.reduce(callback, 0).catch(() => {}); expect(callCount).toBe(1); }); - it("uses the first object as an initial value when no initial value is passed", async () => { + it('uses the first object as an initial value when no initial value is passed', async () => { let callCount = 0; const callback = (accumulator, object) => { callCount += 1; accumulator.attributes.number += object.attributes.number; return accumulator; }; - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); const result = await q.reduce(callback); - expect(result.id).toBe("I55"); + expect(result.id).toBe('I55'); expect(result.attributes.number).toBe(6); expect(callCount).toBe(2); // Not called for the first object when used as initial value }); - it("rejects with a TypeError when there are no results and no initial value was provided", async () => { + it('rejects with a TypeError when there are no results and no initial value was provided', async () => { CoreManager.setQueryController({ aggregate() {}, find() { @@ -2142,7 +2106,7 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); const callback = (accumulator, object) => { accumulator.attributes.number += object.attributes.number; return accumulator; @@ -2151,50 +2115,50 @@ describe("ParseQuery", () => { }); }); - describe("iterating over results with .filter()", () => { + describe('iterating over results with .filter()', () => { beforeEach(() => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ results: [ - { objectId: "I55", size: "medium", name: "Product 55" }, - { objectId: "I89", size: "small", name: "Product 89" }, - { objectId: "I91", size: "small", name: "Product 91" }, + { 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 q = new ParseQuery("Item"); + it('can iterate results with a synchronous callback', async () => { + 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 q = new ParseQuery("Item"); + it('can iterate results with an async callback', async () => { + const callback = async object => object.attributes.size === 'small'; + const q = new ParseQuery('Item'); const results = await q.filter(callback); expect(results.length).toBe(2); }); - it("stops iteration when a rejected promise is returned", async () => { + it('stops iteration when a rejected promise is returned', async () => { let callCount = 0; const callback = async () => { callCount += 1; - return Promise.reject(new Error("Callback rejecting")); + return Promise.reject(new Error('Callback rejecting')); }; - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); await q.filter(callback).catch(() => {}); expect(callCount).toBe(1); }); }); - it("returns an error when iterating over an invalid query", (done) => { - const q = new ParseQuery("Item"); + it('returns an error when iterating over an invalid query', done => { + const q = new ParseQuery('Item'); q.limit(10); q.each(() => {}).then( () => { @@ -2202,76 +2166,72 @@ describe("ParseQuery", () => { expect(true).toBe(false); done(); }, - (err) => { - expect(err).toBe( - "Cannot iterate on a query with sort, skip, or limit." - ); + err => { + expect(err).toBe('Cannot iterate on a query with sort, skip, or limit.'); done(); } ); }); - it("rewrites User queries when the rewrite is enabled", () => { - CoreManager.set("PERFORM_USER_REWRITE", true); - let q = new ParseQuery("User"); - expect(q.className).toBe("_User"); - CoreManager.set("PERFORM_USER_REWRITE", false); - q = new ParseQuery("User"); - expect(q.className).toBe("User"); + it('rewrites User queries when the rewrite is enabled', () => { + CoreManager.set('PERFORM_USER_REWRITE', true); + let q = new ParseQuery('User'); + expect(q.className).toBe('_User'); + CoreManager.set('PERFORM_USER_REWRITE', false); + q = new ParseQuery('User'); + 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) => { - expect(results[0].className).toBe("Product"); + const q = new ParseQuery('Item'); + 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) => { - expect(results[0].className).toBe("Product"); + const q = new ParseQuery('Item'); + 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: "T01", - name: "Name", - other: "other", - className: "Thing", - createdAt: "2017-01-10T10:00:00Z", + objectId: 'T01', + name: 'Name', + other: 'other', + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ @@ -2283,47 +2243,47 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; q.find() - .then((results) => { + .then(results => { testObject = results[0]; - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); - objectToReturn = { objectId: "T01", name: "Name2" }; - const q2 = new ParseQuery("Thing"); + 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(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); + 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: "T01", - name: "Name", - other: "other", - tbd: "exists", - className: "Thing", - createdAt: "2017-01-10T10:00:00Z", - subObject: { key1: "value", key2: "value2", key3: "thisWillGoAway" }, + objectId: 'T01', + name: 'Name', + other: 'other', + tbd: 'exists', + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', + subObject: { key1: 'value', key2: 'value2', key3: 'thisWillGoAway' }, }; CoreManager.setQueryController({ @@ -2335,69 +2295,69 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; return q .find() - .then((results) => { + .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"); + 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"); + const q2 = new ParseQuery('Thing'); + q2.select('other', 'tbd', 'subObject.key1', 'subObject.key3'); objectToReturn = { - objectId: "T01", - other: "other2", - subObject: { key1: "updatedValue" }, + 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 + .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(); + 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(); + 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) => { + 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: "T01", - name: "Name", - other: "other", - className: "Thing", - createdAt: "2017-01-10T10:00:00Z", + objectId: 'T01', + name: 'Name', + other: 'other', + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ @@ -2409,47 +2369,47 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; q.first() - .then((result) => { + .then(result => { testObject = result; - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); - objectToReturn = { objectId: "T01", name: "Name2" }; - const q2 = new ParseQuery("Thing"); + 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(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); + 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); let objectToReturn = { - objectId: "T01", - name: "Name", - other: "other", - tbd: "exists", - className: "Thing", - subObject: { key1: "value", key2: "value2", key3: "thisWillGoAway" }, - createdAt: "2017-01-10T10:00:00Z", + objectId: 'T01', + name: 'Name', + other: 'other', + tbd: 'exists', + className: 'Thing', + subObject: { key1: 'value', key2: 'value2', key3: 'thisWillGoAway' }, + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ @@ -2461,196 +2421,196 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; return q .first() - .then((result) => { + .then(result => { testObject = result; - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); - expect(testObject.has("tbd")).toBe(true); + 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"); + const q2 = new ParseQuery('Thing'); + q2.select('other', 'tbd', 'subObject.key1', 'subObject.key3'); objectToReturn = { - objectId: "T01", - other: "other2", - subObject: { key1: "updatedValue" }, + 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 + .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(); + 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(); + 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) => { + error => { done.fail(error); } ); }); - it("restores queries from json representation", () => { - const q = new ParseQuery("Item"); + it('restores queries from json representation', () => { + const q = new ParseQuery('Item'); - q.include("manufacturer"); - q.select("inStock", "lastPurchase"); + q.include('manufacturer'); + q.select('inStock', 'lastPurchase'); q.limit(10); q.withCount(true); - q.ascending(["a", "b", "c"]); + q.ascending(['a', 'b', 'c']); q.skip(4); - q.equalTo("size", "medium"); + q.equalTo('size', 'medium'); const json = q.toJSON(); - const newQuery = ParseQuery.fromJSON("Item", json); + const newQuery = ParseQuery.fromJSON('Item', json); - expect(newQuery.className).toBe("Item"); + expect(newQuery.className).toBe('Item'); expect(newQuery.toJSON()).toEqual({ - include: "manufacturer", - keys: "inStock,lastPurchase", + include: 'manufacturer', + keys: 'inStock,lastPurchase', limit: 10, count: 1, - order: "a,b,c", + 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ - distinct: "size", + distinct: 'size', where: { - size: "small", + size: 'small', }, }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: ["L"], + results: ['L'], }); }, }); - const q = new ParseQuery("Item"); - q.equalTo("size", "small") - .distinct("size") - .then((results) => { - expect(results[0]).toBe("L"); + const q = new ParseQuery('Item'); + 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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ - distinct: "size", + distinct: 'size', where: { - size: "small", + size: 'small', }, }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + 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", + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') + .distinct('size', { + sessionToken: '1234', }) - .then((results) => { - expect(results[0]).toBe("L"); + .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) { - expect(className).toBe("Item"); + expect(className).toBe('Item'); expect(params).toEqual({ - distinct: "size", + distinct: 'size', where: { - size: "small", + size: 'small', }, - hint: "_id_", + hint: '_id_', }); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + 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", + const q = new ParseQuery('Item'); + q.equalTo('size', 'small') + .hint('_id_') + .distinct('size', { + sessionToken: '1234', }) - .then((results) => { - expect(results[0]).toBe("L"); + .then(results => { + expect(results[0]).toBe('L'); done(); }); }); - it("can issue a query to the controller", () => { - const q = new ParseQuery("Item"); - q.readPreference("PRIMARY", "SECONDARY", "SECONDARY_PREFERRED"); + it('can issue a query to the controller', () => { + const q = new ParseQuery('Item'); + q.readPreference('PRIMARY', 'SECONDARY', 'SECONDARY_PREFERRED'); const json = q.toJSON(); expect(json).toEqual({ where: {}, - readPreference: "PRIMARY", - includeReadPreference: "SECONDARY", - subqueryReadPreference: "SECONDARY_PREFERRED", + readPreference: 'PRIMARY', + includeReadPreference: 'SECONDARY', + subqueryReadPreference: 'SECONDARY_PREFERRED', }); - const query = ParseQuery.fromJSON("Item", json); - expect(query._readPreference).toBe("PRIMARY"); - expect(query._includeReadPreference).toBe("SECONDARY"); - expect(query._subqueryReadPreference).toBe("SECONDARY_PREFERRED"); + const query = ParseQuery.fromJSON('Item', json); + expect(query._readPreference).toBe('PRIMARY'); + expect(query._includeReadPreference).toBe('SECONDARY'); + 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) { - expect(className).toBe("Item"); - expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); + expect(className).toBe('Item'); + expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ @@ -2659,54 +2619,54 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.aggregate(pipeline).then((results) => { + const q = new ParseQuery('Item'); + 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: [], }); }); - const q = new ParseQuery("Item"); - q.equalTo("name", "foo"); - q.aggregate(pipeline).then((results) => { + const q = new ParseQuery('Item'); + q.equalTo('name', 'foo'); + 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({ results: [], }); }); - const q = new ParseQuery("Item"); - q.equalTo("name", "foo"); - q.aggregate(pipeline).then((results) => { + const q = new ParseQuery('Item'); + q.equalTo('name', 'foo'); + 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() {}, aggregate(className, params, options) { - expect(className).toBe("Item"); - expect(params.pipeline).toEqual({ group: { objectId: "$name" } }); + expect(className).toBe('Item'); + expect(params.pipeline).toEqual({ group: { objectId: '$name' } }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ @@ -2715,21 +2675,21 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Item"); - q.aggregate(pipeline).then((results) => { + const q = new ParseQuery('Item'); + 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(className).toBe('Item'); expect(params).toEqual({ - group: { objectId: "$name" }, + group: { objectId: '$name' }, }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); @@ -2740,44 +2700,44 @@ describe("ParseQuery", () => { }); try { - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); q.aggregate(pipeline).then(() => {}); } catch (e) { done(); } }); - 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) { - expect(className).toBe("Item"); - expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); + expect(className).toBe('Item'); + expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [], }); }, }); - const q = new ParseQuery("Item"); + 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() {}, aggregate(className, params, options) { - expect(className).toBe("Item"); - expect(params.readPreference).toEqual("SECONDARY"); + expect(className).toBe('Item'); + expect(params.readPreference).toEqual('SECONDARY'); expect(options.useMasterKey).toEqual(true); return Promise.resolve({ results: [], @@ -2785,41 +2745,41 @@ describe("ParseQuery", () => { }, }); // Query - const q = new ParseQuery("Item"); - q.readPreference("SECONDARY"); - const results = await q.aggregate([], { sessionToken: "1234" }); + const q = new ParseQuery('Item'); + q.readPreference('SECONDARY'); + const results = await q.aggregate([], { sessionToken: '1234' }); // Validate 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) { - expect(className).toBe("Item"); - expect(params.pipeline).toEqual([{ group: { objectId: "$name" } }]); - expect(params.hint).toEqual("_id_"); + expect(className).toBe('Item'); + expect(params.pipeline).toEqual([{ group: { objectId: '$name' } }]); + expect(params.hint).toEqual('_id_'); expect(options.useMasterKey).toEqual(true); - expect(options.sessionToken).toEqual("1234"); + expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [], }); }, }); - const q = new ParseQuery("Item"); - q.hint("_id_") + const q = new ParseQuery('Item'); + q.hint('_id_') .aggregate(pipeline, { - sessionToken: "1234", + sessionToken: '1234', }) - .then((results) => { + .then(results => { expect(results).toEqual([]); done(); }); }); - it("can cancel query", async () => { + it('can cancel query', async () => { const mockRequestTask = { abort: () => {}, }; @@ -2833,12 +2793,12 @@ describe("ParseQuery", () => { }, aggregate: () => {}, }); - const query = new ParseQuery("TestCancel"); + const query = new ParseQuery('TestCancel'); expect(query._xhrRequest).toBeDefined(); expect(query._xhrRequest.task).toBe(null); expect(query._xhrRequest.onchange()).toBeUndefined(); - jest.spyOn(mockRequestTask, "abort"); + jest.spyOn(mockRequestTask, 'abort'); query.cancel(); expect(mockRequestTask.abort).toHaveBeenCalledTimes(0); @@ -2849,21 +2809,21 @@ 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); const objectToReturn = { - objectId: "T01", - name: "Name", - tbd: "exists", - className: "Thing", - createdAt: "2017-01-10T10:00:00Z", + objectId: 'T01', + name: 'Name', + tbd: 'exists', + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ @@ -2875,47 +2835,47 @@ describe("ParseQuery", () => { }, }); - 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) => { + .then(results => { testObject = results[0]; - expect(testObject.get("name")).toBe("Name"); - expect(testObject.has("other")).toBe(false); - expect(testObject.has("subObject")).toBe(false); + expect(testObject.get('name')).toBe('Name'); + expect(testObject.has('other')).toBe(false); + expect(testObject.has('subObject')).toBe(false); }) .then( () => { done(); }, - (error) => { + 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"); - ParseQuery = require("../ParseQuery").default; + ParseObject = require('../ParseObject').default; + CoreManager = require('../CoreManager'); + ParseQuery = require('../ParseQuery').default; ParseObject.enableSingleInstance(); let objectToReturn = { - 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", + 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', }; CoreManager.setQueryController({ @@ -2927,63 +2887,63 @@ describe("ParseQuery", () => { }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; return q .find() - .then((results) => { + .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); + 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"); + const q2 = new ParseQuery('Thing'); q2.select( - "name", - "subObject1", - "subObject2.foo", - "subObject4.foo", - "subObject5.subSubObject.foo" + 'name', + 'subObject1', + 'subObject2.foo', + 'subObject4.foo', + 'subObject5.subSubObject.foo' ); objectToReturn = { - objectId: "T01", - name: "Name", - subObject4: { foo: "bar" }, + 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 + 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) => { + error => { done.fail(error); } ); }); - it("full text search", () => { - const query = new ParseQuery("Item"); - query.fullText("size", "small"); + it('full text search', () => { + const query = new ParseQuery('Item'); + query.fullText('size', 'small'); expect(query.toJSON()).toEqual({ where: { size: { $text: { $search: { - $term: "small", + $term: 'small', }, }, }, @@ -2991,60 +2951,60 @@ describe("ParseQuery", () => { }); }); - it("full text search sort", () => { - const query = new ParseQuery("Item"); - query.fullText("size", "medium"); - query.ascending("$score"); - query.select("$score"); + it('full text search sort', () => { + const query = new ParseQuery('Item'); + query.fullText('size', 'medium'); + query.ascending('$score'); + query.select('$score'); expect(query.toJSON()).toEqual({ where: { size: { $text: { $search: { - $term: "medium", + $term: 'medium', }, }, }, }, - keys: "$score", - order: "$score", + keys: '$score', + order: '$score', }); }); - it("full text search key required", (done) => { - const query = new ParseQuery("Item"); - expect(() => query.fullText()).toThrow("A key is required."); + 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) => { - const query = new ParseQuery("Item"); - expect(() => query.fullText("key")).toThrow("A search term is required"); + 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) => { - const query = new ParseQuery("Item"); - expect(() => query.fullText("key", [])).toThrow( - "The value being searched for must be a string." + 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.' ); done(); }); - it("full text search invalid option", (done) => { - const query = new ParseQuery("Item"); - expect(() => - query.fullText("size", "medium", { unknown: "throwOption" }) - ).toThrow("Unknown option: unknown"); + it('full text search invalid option', done => { + const query = new ParseQuery('Item'); + expect(() => query.fullText('size', 'medium', { unknown: 'throwOption' })).toThrow( + 'Unknown option: unknown' + ); done(); }); - it("full text search with all parameters", () => { - const query = new ParseQuery("Item"); + it('full text search with all parameters', () => { + const query = new ParseQuery('Item'); - query.fullText("size", "medium", { - language: "en", + query.fullText('size', 'medium', { + language: 'en', caseSensitive: false, diacriticSensitive: true, }); @@ -3054,8 +3014,8 @@ describe("ParseQuery", () => { size: { $text: { $search: { - $term: "medium", - $language: "en", + $term: 'medium', + $language: 'en', $caseSensitive: false, $diacriticSensitive: true, }, @@ -3065,10 +3025,10 @@ describe("ParseQuery", () => { }); }); - it("add the score for the full text search", () => { - const query = new ParseQuery("Item"); + it('add the score for the full text search', () => { + const query = new ParseQuery('Item'); - query.fullText("size", "medium", { language: "fr" }); + query.fullText('size', 'medium', { language: 'fr' }); query.sortByTextScore(); expect(query.toJSON()).toEqual({ @@ -3076,28 +3036,28 @@ describe("ParseQuery", () => { size: { $text: { $search: { - $term: "medium", - $language: "fr", + $term: 'medium', + $language: 'fr', }, }, }, }, - keys: "$score", - order: "$score", + keys: '$score', + order: '$score', }); }); }); -describe("ParseQuery LocalDatastore", () => { +describe('ParseQuery LocalDatastore', () => { beforeEach(() => { CoreManager.setLocalDatastore(mockLocalDatastore); jest.clearAllMocks(); }); - it("can query from local datastore", () => { + it('can query from local datastore', () => { mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromLocalDatastore(); @@ -3105,10 +3065,10 @@ describe("ParseQuery LocalDatastore", () => { expect(q._localDatastorePinName).toBe(null); }); - it("can query from default pin", () => { + it('can query from default pin', () => { mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromPin(); @@ -3120,19 +3080,19 @@ describe("ParseQuery LocalDatastore", () => { expect(query).toEqual(q); }); - it("can query from pin with name", () => { + it('can query from pin with name', () => { mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery("Item"); + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); - q.fromPinWithName("test_pin"); + q.fromPinWithName('test_pin'); expect(q._queriesLocalDatastore).toBe(true); - expect(q._localDatastorePinName).toBe("test_pin"); + expect(q._localDatastorePinName).toBe('test_pin'); }); - it("cannot query from local datastore if disabled", () => { - const q = new ParseQuery("Item"); + it('cannot query from local datastore if disabled', () => { + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromLocalDatastore(); @@ -3140,8 +3100,8 @@ describe("ParseQuery LocalDatastore", () => { expect(q._localDatastorePinName).toBe(null); }); - it("can query from default pin if disabled", () => { - const q = new ParseQuery("Item"); + it('can query from default pin if disabled', () => { + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); q.fromPin(); @@ -3149,230 +3109,230 @@ describe("ParseQuery LocalDatastore", () => { expect(q._localDatastorePinName).toBe(null); }); - it("can query from pin with name if disabled", () => { - const q = new ParseQuery("Item"); + it('can query from pin with name if disabled', () => { + const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); - q.fromPinWithName("test_pin"); + q.fromPinWithName('test_pin'); expect(q._queriesLocalDatastore).toBe(false); expect(q._localDatastorePinName).toBe(null); }); - it("can query offline", async () => { + it('can query offline', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', count: 2, }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', }; const obj3 = { - className: "Unknown", - objectId: "objectId3", + className: 'Unknown', + objectId: 'objectId3', }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce( - () => [obj1, obj2, obj3] - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery("Item"); - q.equalTo("count", 2); + const q = new ParseQuery('Item'); + q.equalTo('count', 2); q.fromLocalDatastore(); const results = await q.find(); expect(results[0].id).toEqual(obj1.objectId); }); - it("can query offline with localId", async () => { + it('can query offline with localId', async () => { const obj1 = { - className: "Item", - _localId: "local0", + className: 'Item', + _localId: 'local0', count: 2, }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', }; const obj3 = { - className: "Unknown", - objectId: "objectId3", + className: 'Unknown', + objectId: 'objectId3', }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce( - () => [obj1, obj2, obj3] - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - const q = new ParseQuery("Item"); - q.equalTo("count", 2); + const q = new ParseQuery('Item'); + q.equalTo('count', 2); q.fromLocalDatastore(); const results = await q.find(); expect(results[0]._localId).toEqual(obj1._localId); }); - it("can query offline first", async () => { + it('can query offline first', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', count: 2, }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', }; const obj3 = { - className: "Unknown", - objectId: "objectId3", + className: 'Unknown', + objectId: 'objectId3', }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce( - () => [obj1, obj2, obj3] - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - let q = new ParseQuery("Item"); + let q = new ParseQuery('Item'); q.fromLocalDatastore(); let result = await q.first(); expect(result.id).toEqual(obj1.objectId); jest.clearAllMocks(); - mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce( - () => [] - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => []); mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.fromLocalDatastore(); result = await q.first(); expect(result).toEqual(undefined); }); - it("can query offline sort", async () => { + it('can query offline sort', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', password: 123, number: 2, - createdAt: new Date("2018-08-10T00:00:00.000Z"), - updatedAt: new Date("2018-08-10T00:00:00.000Z"), + createdAt: new Date('2018-08-10T00:00:00.000Z'), + updatedAt: new Date('2018-08-10T00:00:00.000Z'), }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', password: 123, number: 3, - createdAt: new Date("2018-08-11T00:00:00.000Z"), - updatedAt: new Date("2018-08-11T00:00:00.000Z"), + createdAt: new Date('2018-08-11T00:00:00.000Z'), + updatedAt: new Date('2018-08-11T00:00:00.000Z'), }; const obj3 = { - className: "Item", - objectId: "objectId3", + className: 'Item', + objectId: 'objectId3', password: 123, number: 4, - createdAt: new Date("2018-08-12T00:00:00.000Z"), - updatedAt: new Date("2018-08-12T00:00:00.000Z"), + createdAt: new Date('2018-08-12T00:00:00.000Z'), + 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); - let q = new ParseQuery("Item"); - q.ascending("number"); + let q = new ParseQuery('Item'); + q.ascending('number'); q.fromLocalDatastore(); let results = await q.find(); - expect(results[0].get("number")).toEqual(2); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(4); + expect(results[0].get('number')).toEqual(2); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(4); - q = new ParseQuery("Item"); - q.descending("number"); + q = new ParseQuery('Item'); + q.descending('number'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(4); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(2); + expect(results[0].get('number')).toEqual(4); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(2); - q = new ParseQuery("Item"); - q.descending("number"); + q = new ParseQuery('Item'); + q.descending('number'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(4); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(2); + expect(results[0].get('number')).toEqual(4); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(2); - q = new ParseQuery("Item"); - q.descending("_created_at"); + q = new ParseQuery('Item'); + q.descending('_created_at'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(2); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(4); + expect(results[0].get('number')).toEqual(2); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(4); - q = new ParseQuery("Item"); - q.descending("_updated_at"); + q = new ParseQuery('Item'); + q.descending('_updated_at'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(2); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(4); + expect(results[0].get('number')).toEqual(2); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(4); - q = new ParseQuery("Item"); - q.descending("password"); + q = new ParseQuery('Item'); + q.descending('password'); q.fromLocalDatastore(); try { results = await q.find(); } catch (e) { - expect(e.message).toEqual("Invalid Key: password"); + expect(e.message).toEqual('Invalid Key: password'); } }); - it("can query offline sort multiple", async () => { + it('can query offline sort multiple', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', password: 123, number: 3, - string: "a", + string: 'a', }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', number: 1, - string: "b", + string: 'b', }; const obj3 = { - className: "Item", - objectId: "objectId3", + className: 'Item', + objectId: 'objectId3', number: 3, - string: "c", + string: 'c', }; const obj4 = { - className: "Item", - objectId: "objectId4", + className: 'Item', + objectId: 'objectId4', number: 2, - string: "d", + string: 'd', }; mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [ @@ -3384,183 +3344,178 @@ describe("ParseQuery LocalDatastore", () => { mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); - let q = new ParseQuery("Item"); - q.ascending("number,string"); + let q = new ParseQuery('Item'); + q.ascending('number,string'); q.fromLocalDatastore(); let results = await q.find(); - expect(results[0].get("number")).toEqual(1); - expect(results[1].get("number")).toEqual(2); - expect(results[2].get("number")).toEqual(3); - expect(results[3].get("number")).toEqual(3); - expect(results[0].get("string")).toEqual("b"); - expect(results[1].get("string")).toEqual("d"); - expect(results[2].get("string")).toEqual("a"); - expect(results[3].get("string")).toEqual("c"); - - q = new ParseQuery("Item"); - q.ascending("number").addDescending("string"); + expect(results[0].get('number')).toEqual(1); + expect(results[1].get('number')).toEqual(2); + expect(results[2].get('number')).toEqual(3); + expect(results[3].get('number')).toEqual(3); + expect(results[0].get('string')).toEqual('b'); + expect(results[1].get('string')).toEqual('d'); + expect(results[2].get('string')).toEqual('a'); + expect(results[3].get('string')).toEqual('c'); + + q = new ParseQuery('Item'); + q.ascending('number').addDescending('string'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(1); - expect(results[1].get("number")).toEqual(2); - expect(results[2].get("number")).toEqual(3); - expect(results[3].get("number")).toEqual(3); - expect(results[0].get("string")).toEqual("b"); - expect(results[1].get("string")).toEqual("d"); - expect(results[2].get("string")).toEqual("c"); - expect(results[3].get("string")).toEqual("a"); - - q = new ParseQuery("Item"); - q.descending("number,string"); + expect(results[0].get('number')).toEqual(1); + expect(results[1].get('number')).toEqual(2); + expect(results[2].get('number')).toEqual(3); + expect(results[3].get('number')).toEqual(3); + expect(results[0].get('string')).toEqual('b'); + expect(results[1].get('string')).toEqual('d'); + expect(results[2].get('string')).toEqual('c'); + expect(results[3].get('string')).toEqual('a'); + + q = new ParseQuery('Item'); + q.descending('number,string'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(3); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(2); - expect(results[3].get("number")).toEqual(1); - expect(results[0].get("string")).toEqual("c"); - expect(results[1].get("string")).toEqual("a"); - expect(results[2].get("string")).toEqual("d"); - expect(results[3].get("string")).toEqual("b"); - - q = new ParseQuery("Item"); - q.descending("number").addAscending("string"); + expect(results[0].get('number')).toEqual(3); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(2); + expect(results[3].get('number')).toEqual(1); + expect(results[0].get('string')).toEqual('c'); + expect(results[1].get('string')).toEqual('a'); + expect(results[2].get('string')).toEqual('d'); + expect(results[3].get('string')).toEqual('b'); + + q = new ParseQuery('Item'); + q.descending('number').addAscending('string'); q.fromLocalDatastore(); results = await q.find(); - expect(results[0].get("number")).toEqual(3); - expect(results[1].get("number")).toEqual(3); - expect(results[2].get("number")).toEqual(2); - expect(results[3].get("number")).toEqual(1); - expect(results[0].get("string")).toEqual("a"); - expect(results[1].get("string")).toEqual("c"); - expect(results[2].get("string")).toEqual("d"); - expect(results[3].get("string")).toEqual("b"); + expect(results[0].get('number')).toEqual(3); + expect(results[1].get('number')).toEqual(3); + expect(results[2].get('number')).toEqual(2); + expect(results[3].get('number')).toEqual(1); + expect(results[0].get('string')).toEqual('a'); + expect(results[1].get('string')).toEqual('c'); + expect(results[2].get('string')).toEqual('d'); + expect(results[3].get('string')).toEqual('b'); }); - it("can query offline limit", async () => { + it('can query offline limit', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', number: 3, - string: "a", + string: 'a', }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', number: 1, - string: "b", + string: 'b', }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [ - obj1, - obj2, - ]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj2]); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); - let q = new ParseQuery("Item"); + let q = new ParseQuery('Item'); q.limit(0); q.fromLocalDatastore(); let results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(2); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(3); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(-1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); }); - it("can query offline skip", async () => { + it('can query offline skip', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', password: 123, number: 3, - string: "a", + string: 'a', }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', number: 1, - string: "b", + string: 'b', }; const obj3 = { - className: "Item", - objectId: "objectId3", + className: 'Item', + objectId: 'objectId3', number: 2, - string: "c", + string: 'c', }; const objects = [obj1, obj2, obj3]; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation( - () => objects - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => objects); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); - let q = new ParseQuery("Item"); + let q = new ParseQuery('Item'); q.skip(0); q.fromLocalDatastore(); let results = await q.find(); expect(results.length).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.skip(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(2); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.skip(3); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(0); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.skip(4); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(0); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(1); q.skip(2); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(1); q.skip(1); q.fromLocalDatastore(); results = await q.find(); expect(results.length).toEqual(1); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(2); q.skip(1); q.fromLocalDatastore(); @@ -3568,37 +3523,35 @@ describe("ParseQuery LocalDatastore", () => { expect(results.length).toEqual(2); }); - it("can query offline withCount, skip and limit", async () => { + it('can query offline withCount, skip and limit', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", + className: 'Item', + objectId: 'objectId1', password: 123, number: 3, - string: "a", + string: 'a', }; const obj2 = { - className: "Item", - objectId: "objectId2", + className: 'Item', + objectId: 'objectId2', number: 1, - string: "b", + string: 'b', }; const obj3 = { - className: "Item", - objectId: "objectId3", + className: 'Item', + objectId: 'objectId3', number: 2, - string: "c", + string: 'c', }; const objects = [obj1, obj2, obj3]; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation( - () => objects - ); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => objects); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); - let q = new ParseQuery("Item"); + let q = new ParseQuery('Item'); q.skip(0); q.withCount(true); q.fromLocalDatastore(); @@ -3606,7 +3559,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(3); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.skip(1); q.withCount(true); q.fromLocalDatastore(); @@ -3614,7 +3567,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(2); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.skip(3); q.withCount(true); q.fromLocalDatastore(); @@ -3622,7 +3575,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(0); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.withCount(true); q.skip(4); q.fromLocalDatastore(); @@ -3630,7 +3583,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(0); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(1); q.skip(2); q.withCount(true); @@ -3639,7 +3592,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(1); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(1); q.skip(1); q.withCount(true); @@ -3648,7 +3601,7 @@ describe("ParseQuery LocalDatastore", () => { expect(result.results.length).toEqual(1); expect(result.count).toEqual(3); - q = new ParseQuery("Item"); + q = new ParseQuery('Item'); q.limit(2); q.skip(1); q.withCount(true); @@ -3658,163 +3611,145 @@ describe("ParseQuery LocalDatastore", () => { expect(result.count).toEqual(3); }); - it("can query offline select keys", async () => { + it('can query offline select keys', async () => { const obj1 = { - className: "Item", - objectId: "objectId1", - foo: "baz", + className: 'Item', + objectId: 'objectId1', + foo: 'baz', bar: 1, }; - mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [ - obj1, - ]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1]); mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); - const q = new ParseQuery("Item"); - q.select("foo"); + const q = new ParseQuery('Item'); + q.select('foo'); q.fromLocalDatastore(); const results = await q.find(); - expect(results[0].get("foo")).toEqual("baz"); + expect(results[0].get('foo')).toEqual('baz'); }); - it("can subscribe to query if client is already open", async () => { + it('can subscribe to query if client is already open', async () => { const mockLiveQueryClient = { shouldOpen: function () { return false; }, subscribe: function (query, sessionToken) { - const subscription = new LiveQuerySubscription( - "0", - query, - sessionToken - ); + const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set("UserController", { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - CoreManager.set("LiveQueryController", { + CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); }, }); - const query = new ParseQuery("TestObject"); + const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); - expect(subscription.id).toBe("0"); - expect(subscription.sessionToken).toBe("token"); + expect(subscription.id).toBe('0'); + expect(subscription.sessionToken).toBe('token'); expect(subscription.query).toEqual(query); }); - it("can subscribe to query if client is not open", async () => { + it('can subscribe to query if client is not open', async () => { const mockLiveQueryClient = { shouldOpen: function () { return true; }, open: function () {}, subscribe: function (query, sessionToken) { - const subscription = new LiveQuerySubscription( - "0", - query, - sessionToken - ); + const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set("UserController", { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { - return "token"; + return 'token'; }, }); }, }); - CoreManager.set("LiveQueryController", { + CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); }, }); - const query = new ParseQuery("TestObject"); + const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); - expect(subscription.id).toBe("0"); - expect(subscription.sessionToken).toBe("token"); + expect(subscription.id).toBe('0'); + expect(subscription.sessionToken).toBe('token'); expect(subscription.query).toEqual(query); }); - it("can subscribe to query without sessionToken", async () => { + it('can subscribe to query without sessionToken', async () => { const mockLiveQueryClient = { shouldOpen: function () { return true; }, open: function () {}, subscribe: function (query, sessionToken) { - const subscription = new LiveQuerySubscription( - "0", - query, - sessionToken - ); + const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set("UserController", { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(null); }, }); - CoreManager.set("LiveQueryController", { + CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); }, }); - const query = new ParseQuery("TestObject"); + const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); - expect(subscription.id).toBe("0"); + expect(subscription.id).toBe('0'); expect(subscription.sessionToken).toBeUndefined(); expect(subscription.query).toEqual(query); }); - it("can subscribe to query with sessionToken parameter", async () => { + it('can subscribe to query with sessionToken parameter', async () => { const mockLiveQueryClient = { shouldOpen: function () { return true; }, open: function () {}, subscribe: function (query, sessionToken) { - const subscription = new LiveQuerySubscription( - "0", - query, - sessionToken - ); + const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; }, }; - CoreManager.set("UserController", { + CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(null); }, }); - CoreManager.set("LiveQueryController", { + CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); }, }); - const query = new ParseQuery("TestObject"); - const subscription = await query.subscribe("r:test"); - expect(subscription.id).toBe("0"); - expect(subscription.sessionToken).toBe("r:test"); + const query = new ParseQuery('TestObject'); + const subscription = await query.subscribe('r:test'); + expect(subscription.id).toBe('0'); + expect(subscription.sessionToken).toBe('r:test'); expect(subscription.query).toEqual(query); }); }); diff --git a/src/__tests__/ParseRelation-test.js b/src/__tests__/ParseRelation-test.js index d6d2986cb..c2514ca90 100644 --- a/src/__tests__/ParseRelation-test.js +++ b/src/__tests__/ParseRelation-test.js @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../encode"); -jest.dontMock("../ParseRelation"); -jest.dontMock("../ParseOp"); -jest.dontMock("../unique"); +jest.dontMock('../encode'); +jest.dontMock('../ParseRelation'); +jest.dontMock('../ParseOp'); +jest.dontMock('../unique'); const mockStore = {}; const mockObject = function (className) { @@ -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; @@ -52,7 +48,7 @@ mockObject.prototype = { return finalOp; }, }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); const mockQuery = function (className) { this.className = className; @@ -65,238 +61,228 @@ mockQuery.prototype = { this.where[key][comparison] = value; }, }; -jest.setMock("../ParseQuery", mockQuery); +jest.setMock('../ParseQuery', mockQuery); -const ParseObject = require("../ParseObject"); -const ParseRelation = require("../ParseRelation").default; +const ParseObject = require('../ParseObject'); +const ParseRelation = require('../ParseRelation').default; -describe("ParseRelation", () => { - it("can be constructed with a reference parent and key", () => { - const parent = new ParseObject("Item"); - parent.id = "I1"; - const r = new ParseRelation(parent, "shipments"); +describe('ParseRelation', () => { + it('can be constructed with a reference parent and key', () => { + const parent = new ParseObject('Item'); + parent.id = 'I1'; + const r = new ParseRelation(parent, 'shipments'); expect(r.parent).toBe(parent); - expect(r.key).toBe("shipments"); + expect(r.key).toBe('shipments'); expect(r.targetClassName).toBe(null); }); - it("can add objects to a relation", () => { - const parent = new ParseObject("Item"); - parent.id = "I1"; - const r = new ParseRelation(parent, "shipments"); - const o = new ParseObject("Delivery"); - o.id = "D1"; + it('can add objects to a relation', () => { + const parent = new ParseObject('Item'); + parent.id = 'I1'; + const r = new ParseRelation(parent, 'shipments'); + const o = new ParseObject('Delivery'); + o.id = 'D1'; const p = r.add(o); expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "AddRelation", - objects: [{ __type: "Pointer", objectId: "D1", className: "Delivery" }], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'AddRelation', + objects: [{ __type: 'Pointer', objectId: 'D1', className: 'Delivery' }], }); - const o2 = new ParseObject("Delivery"); - o2.id = "D2"; - const o3 = new ParseObject("Delivery"); - o3.id = "D3"; + const o2 = new ParseObject('Delivery'); + o2.id = 'D2'; + const o3 = new ParseObject('Delivery'); + o3.id = 'D3'; r.add([o2, o3]); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "AddRelation", + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'AddRelation', objects: [ - { __type: "Pointer", objectId: "D1", className: "Delivery" }, - { __type: "Pointer", objectId: "D2", className: "Delivery" }, - { __type: "Pointer", objectId: "D3", className: "Delivery" }, + { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, + { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, + { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, ], }); }); - it("can add empty array to a relation", () => { - const parent = new ParseObject("Item"); - parent.id = "I1234"; - const r = new ParseRelation(parent, "shipments"); - const o = new ParseObject("Delivery"); - o.id = "D1234"; + it('can add empty array to a relation', () => { + const parent = new ParseObject('Item'); + parent.id = 'I1234'; + const r = new ParseRelation(parent, 'shipments'); + const o = new ParseObject('Delivery'); + o.id = 'D1234'; const p = r.add(o); expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "AddRelation", - objects: [ - { __type: "Pointer", objectId: "D1234", className: "Delivery" }, - ], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'AddRelation', + 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", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "AddRelation", - objects: [ - { __type: "Pointer", objectId: "D1234", className: "Delivery" }, - ], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'AddRelation', + objects: [{ __type: 'Pointer', objectId: 'D1234', className: 'Delivery' }], }); }); - it("cannot add to relation without parent", () => { + it('cannot add to relation without parent', () => { 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", () => { + 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", () => { + 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", () => { - const parent = new ParseObject("Item"); - parent.id = "I2"; - const r = new ParseRelation(parent, "shipments"); - const o = new ParseObject("Delivery"); - o.id = "D1"; + it('can remove objects from a relation', () => { + const parent = new ParseObject('Item'); + parent.id = 'I2'; + const r = new ParseRelation(parent, 'shipments'); + const o = new ParseObject('Delivery'); + o.id = 'D1'; r.remove(o); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "RemoveRelation", - objects: [{ __type: "Pointer", objectId: "D1", className: "Delivery" }], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'RemoveRelation', + objects: [{ __type: 'Pointer', objectId: 'D1', className: 'Delivery' }], }); - const o2 = new ParseObject("Delivery"); - o2.id = "D2"; - const o3 = new ParseObject("Delivery"); - o3.id = "D3"; + const o2 = new ParseObject('Delivery'); + o2.id = 'D2'; + const o3 = new ParseObject('Delivery'); + o3.id = 'D3'; r.remove([o2, o3]); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "RemoveRelation", + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'RemoveRelation', objects: [ - { __type: "Pointer", objectId: "D1", className: "Delivery" }, - { __type: "Pointer", objectId: "D2", className: "Delivery" }, - { __type: "Pointer", objectId: "D3", className: "Delivery" }, + { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, + { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, + { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, ], }); }); - it("can remove empty array from a relation", () => { - const parent = new ParseObject("Item"); - parent.id = "I5678"; - const r = new ParseRelation(parent, "shipments"); - const o = new ParseObject("Delivery"); - o.id = "D5678"; + it('can remove empty array from a relation', () => { + const parent = new ParseObject('Item'); + parent.id = 'I5678'; + const r = new ParseRelation(parent, 'shipments'); + const o = new ParseObject('Delivery'); + o.id = 'D5678'; r.remove(o); expect(r.toJSON()).toEqual({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "RemoveRelation", - objects: [ - { __type: "Pointer", objectId: "D5678", className: "Delivery" }, - ], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'RemoveRelation', + 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", + __type: 'Relation', + className: 'Delivery', }); - expect(parent.op("shipments").toJSON()).toEqual({ - __op: "RemoveRelation", - objects: [ - { __type: "Pointer", objectId: "D5678", className: "Delivery" }, - ], + expect(parent.op('shipments').toJSON()).toEqual({ + __op: 'RemoveRelation', + objects: [{ __type: 'Pointer', objectId: 'D5678', className: 'Delivery' }], }); }); - it("can generate a query for relation objects", () => { - const parent = new ParseObject("Item"); - parent.id = "I1"; - let r = new ParseRelation(parent, "shipments"); + it('can generate a query for relation objects', () => { + const parent = new ParseObject('Item'); + parent.id = 'I1'; + let r = new ParseRelation(parent, 'shipments'); let q = r.query(); - expect(q.className).toBe("Item"); + 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", + __type: 'Pointer', + objectId: 'I1', + className: 'Item', }, - key: "shipments", + key: 'shipments', }, }); - r = new ParseRelation(parent, "shipments"); - const o = new ParseObject("Delivery"); - o.id = "D1"; + r = new ParseRelation(parent, 'shipments'); + const o = new ParseObject('Delivery'); + o.id = 'D1'; r.add(o); q = r.query(); - expect(q.className).toBe("Delivery"); + expect(q.className).toBe('Delivery'); expect(q.where).toEqual({ $relatedTo: { object: { - __type: "Pointer", - className: "Item", - objectId: "I1", + __type: 'Pointer', + className: 'Item', + objectId: 'I1', }, - key: "shipments", + key: 'shipments', }, }); }); - it("can ensure it relates to the correct parent and key", () => { - 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(new ParseObject("TestObject"), "shipments"); - }).toThrow( - "Internal Error. Relation retrieved from two different Objects." + it('can ensure it relates to the correct parent and key', () => { + 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, parent, "partners")).toThrow( - "Internal Error. Relation retrieved from two different keys." + 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.' ); - expect(r._ensureParentAndKey.bind(r, parent, "shipments")).not.toThrow(); + expect(r._ensureParentAndKey.bind(r, parent, 'shipments')).not.toThrow(); const noParent = new ParseRelation(null, null); noParent._ensureParentAndKey(parent); expect(noParent.parent).toEqual(parent); - const noIdParent = new ParseObject("Item"); - const newParent = new ParseObject("Item"); - newParent.id = "newId"; + const noIdParent = new ParseObject('Item'); + const newParent = new ParseObject('Item'); + newParent.id = 'newId'; const hasParent = new ParseRelation(noIdParent); hasParent._ensureParentAndKey(newParent); diff --git a/src/__tests__/ParseRole-test.js b/src/__tests__/ParseRole-test.js index 00e436832..e2e7fa0ff 100644 --- a/src/__tests__/ParseRole-test.js +++ b/src/__tests__/ParseRole-test.js @@ -7,51 +7,51 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParseRole"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../UniqueInstanceStateController"); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParseRole'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../UniqueInstanceStateController'); -const ParseACL = require("../ParseACL").default; -const ParseError = require("../ParseError").default; -const ParseObject = require("../ParseObject").default; -const ParseRelation = require("../ParseRelation").default; -const ParseRole = require("../ParseRole").default; +const ParseACL = require('../ParseACL').default; +const ParseError = require('../ParseError').default; +const ParseObject = require('../ParseObject').default; +const ParseRelation = require('../ParseRelation').default; +const ParseRole = require('../ParseRole').default; -describe("ParseRole", () => { +describe('ParseRole', () => { beforeEach(() => { ParseObject.disableSingleInstance(); }); - it("can create Roles", () => { + it('can create Roles', () => { let role = new ParseRole(); expect(role.getName()).toBe(undefined); expect(role.getACL()).toBe(null); const acl = new ParseACL({ aUserId: { read: true, write: true } }); - role = new ParseRole("admin", acl); - expect(role.getName()).toBe("admin"); + role = new ParseRole('admin', acl); + expect(role.getName()).toBe('admin'); expect(role.getACL()).toBe(acl); }); - it("handle non string name", () => { + it('handle non string name', () => { const role = new ParseRole(); role.get = () => 1234; - expect(role.getName()).toBe(""); + expect(role.getName()).toBe(''); }); - it("can validate attributes", () => { + it('can validate attributes', () => { const acl = new ParseACL({ aUserId: { read: true, write: true } }); - const role = new ParseRole("admin", acl); - role.id = "101"; + const role = new ParseRole('admin', acl); + role.id = '101'; expect( role.validate({ - name: "author", + name: 'author', }) ).toEqual( new ParseError( @@ -65,45 +65,42 @@ describe("ParseRole", () => { role.validate({ name: 12, }) - ).toEqual( - new ParseError(ParseError.OTHER_CAUSE, "A role's name must be a String.") - ); + ).toEqual(new ParseError(ParseError.OTHER_CAUSE, "A role's name must be a String.")); expect( role.validate({ - name: "$$$", + name: '$$$', }) ).toEqual( 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.' ) ); expect( role.validate({ - name: "admin", + name: 'admin', }) ).toBe(false); const result = role.validate({ - "invalid#field": "admin", + 'invalid#field': 'admin', }); expect(result.code).toBe(ParseError.INVALID_KEY_NAME); }); - it("can be constructed from JSON", () => { + it('can be constructed from JSON', () => { const role = ParseObject.fromJSON({ - className: "_Role", - objectId: "102", - name: "admin", + className: '_Role', + objectId: '102', + name: 'admin', }); expect(role instanceof ParseObject).toBe(true); expect(role instanceof ParseRole).toBe(true); - expect(role.getName()).toBe("admin"); + expect(role.getName()).toBe('admin'); }); - it("can get relations", () => { + it('can get relations', () => { const role = new ParseRole(); expect(role.getUsers() instanceof ParseRelation).toBe(true); expect(role.getRoles() instanceof ParseRelation).toBe(true); diff --git a/src/__tests__/ParseSchema-test.js b/src/__tests__/ParseSchema-test.js index 86a1622b8..f1ad11f9b 100644 --- a/src/__tests__/ParseSchema-test.js +++ b/src/__tests__/ParseSchema-test.js @@ -15,33 +15,33 @@ const mockObject = function (className, id) { this.toPointer = function () { return { className: this.className, - __type: "Pointer", + __type: 'Pointer', objectId: this.id, }; }; }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const ParseObject = require("../ParseObject"); -const ParseSchema = require("../ParseSchema").default; -const CoreManager = require("../CoreManager"); +const ParseObject = require('../ParseObject'); +const ParseSchema = require('../ParseSchema').default; +const CoreManager = require('../CoreManager'); const defaultController = CoreManager.getSchemaController(); -describe("ParseSchema", () => { - it("can create schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - expect(schema.className).toEqual("SchemaTest"); +describe('ParseSchema', () => { + it('can create schema', done => { + const schema = new ParseSchema('SchemaTest'); + expect(schema.className).toEqual('SchemaTest'); done(); }); - it("can create schema with User Class", (done) => { - const schema = new ParseSchema("User"); - expect(schema.className).toEqual("_User"); + 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,89 +50,87 @@ describe("ParseSchema", () => { } }); - it("can create schema fields", (done) => { - const schema = new ParseSchema("SchemaTest"); + it('can create schema fields', done => { + const schema = new ParseSchema('SchemaTest'); schema - .addField("defaultFieldString") - .addString("stringField") - .addNumber("numberField") - .addBoolean("booleanField") - .addDate("dateField") - .addFile("fileField") - .addGeoPoint("geoPointField") - .addPolygon("polygonField") - .addArray("arrayField") - .addObject("objectField") - .addPointer("pointerField", "_User") - .addRelation("relationField", "_User"); - - expect(schema._fields.defaultFieldString.type).toEqual("String"); - expect(schema._fields.stringField.type).toEqual("String"); - expect(schema._fields.numberField.type).toEqual("Number"); - expect(schema._fields.booleanField.type).toEqual("Boolean"); - expect(schema._fields.dateField.type).toEqual("Date"); - expect(schema._fields.fileField.type).toEqual("File"); - expect(schema._fields.geoPointField.type).toEqual("GeoPoint"); - expect(schema._fields.polygonField.type).toEqual("Polygon"); - expect(schema._fields.arrayField.type).toEqual("Array"); - expect(schema._fields.objectField.type).toEqual("Object"); - expect(schema._fields.pointerField.type).toEqual("Pointer"); - expect(schema._fields.relationField.type).toEqual("Relation"); - expect(schema._fields.pointerField.targetClass).toEqual("_User"); - expect(schema._fields.relationField.targetClass).toEqual("_User"); + .addField('defaultFieldString') + .addString('stringField') + .addNumber('numberField') + .addBoolean('booleanField') + .addDate('dateField') + .addFile('fileField') + .addGeoPoint('geoPointField') + .addPolygon('polygonField') + .addArray('arrayField') + .addObject('objectField') + .addPointer('pointerField', '_User') + .addRelation('relationField', '_User'); + + expect(schema._fields.defaultFieldString.type).toEqual('String'); + expect(schema._fields.stringField.type).toEqual('String'); + expect(schema._fields.numberField.type).toEqual('Number'); + expect(schema._fields.booleanField.type).toEqual('Boolean'); + expect(schema._fields.dateField.type).toEqual('Date'); + expect(schema._fields.fileField.type).toEqual('File'); + expect(schema._fields.geoPointField.type).toEqual('GeoPoint'); + expect(schema._fields.polygonField.type).toEqual('Polygon'); + expect(schema._fields.arrayField.type).toEqual('Array'); + expect(schema._fields.objectField.type).toEqual('Object'); + expect(schema._fields.pointerField.type).toEqual('Pointer'); + expect(schema._fields.relationField.type).toEqual('Relation'); + expect(schema._fields.pointerField.targetClass).toEqual('_User'); + expect(schema._fields.relationField.targetClass).toEqual('_User'); done(); }); - it("can create schema fields required and default values", () => { - const object = new ParseObject("TestObject", "1234"); - const schema = new ParseSchema("SchemaTest"); + it('can create schema fields required and default values', () => { + const object = new ParseObject('TestObject', '1234'); + const schema = new ParseSchema('SchemaTest'); schema - .addField("defaultFieldString", "String", { + .addField('defaultFieldString', 'String', { required: true, - defaultValue: "hello", + defaultValue: 'hello', }) - .addDate("dateField", { + .addDate('dateField', { required: true, - defaultValue: "2000-01-01T00:00:00.000Z", + defaultValue: '2000-01-01T00:00:00.000Z', }) - .addPointer("pointerField", "TestObject", { + .addPointer('pointerField', 'TestObject', { required: true, defaultValue: object, }) - .addPointer("pointerJSONField", "TestObject", { + .addPointer('pointerJSONField', 'TestObject', { required: true, defaultValue: object.toPointer(), }); - expect(schema._fields.defaultFieldString.type).toEqual("String"); + expect(schema._fields.defaultFieldString.type).toEqual('String'); expect(schema._fields.defaultFieldString.required).toEqual(true); - expect(schema._fields.defaultFieldString.defaultValue).toEqual("hello"); - expect(schema._fields.pointerField.type).toEqual("Pointer"); - expect(schema._fields.pointerField.targetClass).toEqual("TestObject"); + expect(schema._fields.defaultFieldString.defaultValue).toEqual('hello'); + expect(schema._fields.pointerField.type).toEqual('Pointer'); + expect(schema._fields.pointerField.targetClass).toEqual('TestObject'); expect(schema._fields.pointerField.required).toEqual(true); - expect(schema._fields.pointerField.defaultValue).toEqual( - object.toPointer() - ); + expect(schema._fields.pointerField.defaultValue).toEqual(object.toPointer()); expect(schema._fields.dateField).toEqual({ - type: "Date", + type: 'Date', required: true, defaultValue: { - __type: "Date", - iso: new Date("2000-01-01T00:00:00.000Z"), + __type: 'Date', + iso: new Date('2000-01-01T00:00:00.000Z'), }, }); }); - it("can create schema indexes", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.addIndex("testIndex", { name: 1 }); + it('can create schema indexes', done => { + const schema = new ParseSchema('SchemaTest'); + schema.addIndex('testIndex', { name: 1 }); expect(schema._indexes.testIndex.name).toBe(1); done(); }); - it("can set schema class level permissions", (done) => { - const schema = new ParseSchema("SchemaTest"); + it('can set schema class level permissions', done => { + const schema = new ParseSchema('SchemaTest'); expect(schema._clp).toBeUndefined(); schema.setCLP(undefined); expect(schema._clp).toBeUndefined(); @@ -142,7 +140,7 @@ describe("ParseSchema", () => { get: { requiresAuthentication: true }, find: {}, count: {}, - create: { "*": true }, + create: { '*': true }, update: { requiresAuthentication: true }, delete: {}, addField: {}, @@ -153,93 +151,93 @@ describe("ParseSchema", () => { 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"); + const schema = new ParseSchema('SchemaTest'); + schema.addField(null, 'string'); } catch (e) { done(); } }); - 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"); + const schema = new ParseSchema('SchemaTest'); + schema.addField('testField', 'unknown'); } catch (e) { done(); } }); - it("cannot add index with null name", (done) => { + it('cannot add index with null name', done => { try { - const schema = new ParseSchema("SchemaTest"); + const schema = new ParseSchema('SchemaTest'); 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); + const schema = new ParseSchema('SchemaTest'); + schema.addIndex('testIndex', null); } catch (e) { done(); } }); - 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"); + const schema = new ParseSchema('SchemaTest'); + schema.addPointer(null, 'targetClass'); } catch (e) { done(); } }); - 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); + const schema = new ParseSchema('SchemaTest'); + schema.addPointer('pointerField', null); } catch (e) { done(); } }); - 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"); + const schema = new ParseSchema('SchemaTest'); + schema.addRelation(null, 'targetClass'); } catch (e) { done(); } }); - 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); + const schema = new ParseSchema('SchemaTest'); + schema.addRelation('relationField', null); } catch (e) { done(); } }); - it("can delete schema field", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.deleteField("testField"); - expect(schema._fields.testField).toEqual({ __op: "Delete" }); + it('can delete schema field', done => { + const schema = new ParseSchema('SchemaTest'); + schema.deleteField('testField'); + expect(schema._fields.testField).toEqual({ __op: 'Delete' }); done(); }); - it("can delete schema index", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.deleteIndex("testIndex"); - expect(schema._indexes.testIndex).toEqual({ __op: "Delete" }); + it('can delete schema index', done => { + const schema = new ParseSchema('SchemaTest'); + schema.deleteIndex('testIndex'); + expect(schema._indexes.testIndex).toEqual({ __op: 'Delete' }); done(); }); - it("can save schema", (done) => { + it('can save schema', done => { CoreManager.setSchemaController({ send() {}, get() {}, @@ -247,26 +245,26 @@ describe("ParseSchema", () => { delete() {}, purge() {}, create(className, params) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); expect(params).toEqual({ - className: "SchemaTest", - fields: { name: { type: "String" } }, + className: 'SchemaTest', + fields: { name: { type: 'String' } }, indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, }); - const schema = new ParseSchema("SchemaTest"); - schema.addField("name"); - schema.addIndex("testIndex", { name: 1 }); - schema.save().then((results) => { + const schema = new ParseSchema('SchemaTest'); + schema.addField('name'); + 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() {}, @@ -274,26 +272,26 @@ describe("ParseSchema", () => { delete() {}, purge() {}, update(className, params) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); expect(params).toEqual({ - className: "SchemaTest", - fields: { name: { type: "String" } }, + className: 'SchemaTest', + fields: { name: { type: 'String' } }, indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, }); - const schema = new ParseSchema("SchemaTest"); - schema.addField("name"); - schema.addIndex("testIndex", { name: 1 }); - schema.update().then((results) => { + const schema = new ParseSchema('SchemaTest'); + schema.addField('name'); + 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() {}, @@ -301,19 +299,19 @@ describe("ParseSchema", () => { get() {}, purge() {}, delete(className) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); return Promise.resolve([]); }, }); - const schema = new ParseSchema("SchemaTest"); - schema.delete().then((results) => { + const schema = new ParseSchema('SchemaTest'); + schema.delete().then(results => { expect(results).toEqual([]); done(); }); }); - it("can purge schema", (done) => { + it('can purge schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -321,19 +319,19 @@ describe("ParseSchema", () => { get() {}, delete() {}, purge(className) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); return Promise.resolve([]); }, }); - const schema = new ParseSchema("SchemaTest"); - schema.purge().then((results) => { + const schema = new ParseSchema('SchemaTest'); + schema.purge().then(results => { expect(results).toEqual([]); done(); }); }); - it("can get schema", (done) => { + it('can get schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -341,19 +339,19 @@ describe("ParseSchema", () => { delete() {}, purge() {}, get(className) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); return Promise.resolve([]); }, }); - const schema = new ParseSchema("SchemaTest"); - schema.get().then((results) => { + const schema = new ParseSchema('SchemaTest'); + schema.get().then(results => { expect(results).toEqual([]); done(); }); }); - it("cannot get empty schema", (done) => { + it('cannot get empty schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -361,26 +359,26 @@ describe("ParseSchema", () => { delete() {}, purge() {}, get(className) { - expect(className).toBe("SchemaTest"); + expect(className).toBe('SchemaTest'); return Promise.resolve(null); }, }); - const schema = new ParseSchema("SchemaTest"); + const schema = new ParseSchema('SchemaTest'); schema.get().then( () => { // Should never reach expect(true).toBe(false); done(); }, - (error) => { - expect(error.message).toBe("Schema not found."); + 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() {}, @@ -388,20 +386,20 @@ describe("ParseSchema", () => { delete() {}, purge() {}, get(className) { - expect(className).toBe(""); + expect(className).toBe(''); return Promise.resolve({ - results: ["all"], + results: ['all'], }); }, }); - ParseSchema.all().then((results) => { - expect(results[0]).toEqual("all"); + 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() {}, @@ -409,7 +407,7 @@ describe("ParseSchema", () => { delete() {}, purge() {}, get(className) { - expect(className).toBe(""); + expect(className).toBe(''); return Promise.resolve({ results: [], }); @@ -422,15 +420,15 @@ describe("ParseSchema", () => { expect(true).toBe(false); done(); }, - (error) => { - expect(error.message).toBe("Schema not found."); + error => { + expect(error.message).toBe('Schema not found.'); done(); } ); }); }); -describe("SchemaController", () => { +describe('SchemaController', () => { beforeEach(() => { CoreManager.setSchemaController(defaultController); const request = function () { @@ -442,41 +440,41 @@ describe("SchemaController", () => { CoreManager.setRESTController({ request: request, ajax: ajax }); }); - it("save schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.save().then((results) => { + it('save schema', done => { + const schema = new ParseSchema('SchemaTest'); + schema.save().then(results => { expect(results).toEqual([]); done(); }); }); - it("get schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.get().then((results) => { + it('get schema', done => { + const schema = new ParseSchema('SchemaTest'); + schema.get().then(results => { expect(results).toEqual([]); done(); }); }); - it("update schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.update().then((results) => { + it('update schema', done => { + const schema = new ParseSchema('SchemaTest'); + schema.update().then(results => { expect(results).toEqual([]); done(); }); }); - it("delete schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.delete().then((results) => { + it('delete schema', done => { + const schema = new ParseSchema('SchemaTest'); + schema.delete().then(results => { expect(results).toEqual([]); done(); }); }); - it("purge schema", (done) => { - const schema = new ParseSchema("SchemaTest"); - schema.purge().then((results) => { + it('purge schema', done => { + const schema = new ParseSchema('SchemaTest'); + schema.purge().then(results => { expect(results).toEqual([]); done(); }); diff --git a/src/__tests__/ParseSession-test.js b/src/__tests__/ParseSession-test.js index 5706fad8b..9a9766499 100644 --- a/src/__tests__/ParseSession-test.js +++ b/src/__tests__/ParseSession-test.js @@ -7,24 +7,24 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../isRevocableSession"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../parseDate"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParseSession"); -jest.dontMock("../RESTController"); -jest.dontMock("../Storage"); -jest.dontMock("../StorageController.default"); -jest.dontMock("../TaskQueue"); -jest.dontMock("../unique"); -jest.dontMock("../UniqueInstanceStateController"); - -jest.dontMock("./test_helpers/mockXHR"); +jest.dontMock('../CoreManager'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../isRevocableSession'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../parseDate'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParseSession'); +jest.dontMock('../RESTController'); +jest.dontMock('../Storage'); +jest.dontMock('../StorageController.default'); +jest.dontMock('../TaskQueue'); +jest.dontMock('../unique'); +jest.dontMock('../UniqueInstanceStateController'); + +jest.dontMock('./test_helpers/mockXHR'); const mockUser = function (token) { this.token = token; @@ -35,73 +35,73 @@ mockUser.prototype.getSessionToken = function () { mockUser.current = function () { return null; }; -jest.setMock("../ParseUser", mockUser); +jest.setMock('../ParseUser', mockUser); -const CoreManager = require("../CoreManager"); -const ParseObject = require("../ParseObject").default; -const ParseSession = require("../ParseSession").default; +const CoreManager = require('../CoreManager'); +const ParseObject = require('../ParseObject').default; +const ParseSession = require('../ParseSession').default; -CoreManager.set("APPLICATION_ID", "A"); -CoreManager.set("JAVASCRIPT_KEY", "B"); +CoreManager.set('APPLICATION_ID', 'A'); +CoreManager.set('JAVASCRIPT_KEY', 'B'); -describe("ParseSession", () => { - it("can be initialized", () => { +describe('ParseSession', () => { + it('can be initialized', () => { let session = new ParseSession(); - session.set("someField", "someValue"); - expect(session.getSessionToken()).toBe(""); - expect(session.get("someField")).toBe("someValue"); + session.set('someField', 'someValue'); + expect(session.getSessionToken()).toBe(''); + expect(session.get('someField')).toBe('someValue'); session = new ParseSession({ - someField: "someValue", + someField: 'someValue', }); - expect(session.get("someField")).toBe("someValue"); + expect(session.get('someField')).toBe('someValue'); }); - it("cannot create schema with invalid fields", () => { + 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"); }); - it("cannot write to readonly fields", () => { + it('cannot write to readonly fields', () => { const session = new ParseSession(); - expect(session.set.bind(session, "createdWith", "facebook")).toThrow( - "Cannot modify readonly attribute: createdWith" + expect(session.set.bind(session, 'createdWith', 'facebook')).toThrow( + 'Cannot modify readonly attribute: createdWith' ); - expect(session.set.bind(session, "expiresAt", new Date())).toThrow( - "Cannot modify readonly attribute: expiresAt" + expect(session.set.bind(session, 'expiresAt', new Date())).toThrow( + 'Cannot modify readonly attribute: expiresAt' ); - expect(session.set.bind(session, "installationId", "iid")).toThrow( - "Cannot modify readonly attribute: installationId" + expect(session.set.bind(session, 'installationId', 'iid')).toThrow( + 'Cannot modify readonly attribute: installationId' ); - expect(session.set.bind(session, "restricted", true)).toThrow( - "Cannot modify readonly attribute: restricted" + expect(session.set.bind(session, 'restricted', true)).toThrow( + 'Cannot modify readonly attribute: restricted' ); - expect(session.set.bind(session, "sessionToken", "st")).toThrow( - "Cannot modify readonly attribute: sessionToken" + expect(session.set.bind(session, 'sessionToken', 'st')).toThrow( + 'Cannot modify readonly attribute: sessionToken' ); - expect(session.set.bind(session, "user", null)).toThrow( - "Cannot modify readonly attribute: user" + expect(session.set.bind(session, 'user', null)).toThrow( + 'Cannot modify readonly attribute: user' ); }); - it("exposes the token through a getter", () => { + it('exposes the token through a getter', () => { const session = new ParseSession(); session._finishFetch({ - id: "session1", - sessionToken: "abc123", + id: 'session1', + sessionToken: 'abc123', }); - expect(session.getSessionToken()).toBe("abc123"); + expect(session.getSessionToken()).toBe('abc123'); }); - it("checks the current user for a revocable token", () => { + it('checks the current user for a revocable token', () => { expect(ParseSession.isCurrentSessionRevocable()).toBe(false); mockUser.current = function () { - return new mockUser("r:abc123"); + return new mockUser('r:abc123'); }; expect(ParseSession.isCurrentSessionRevocable()).toBe(true); mockUser.current = function () { - return new mockUser("abc123"); + return new mockUser('abc123'); }; expect(ParseSession.isCurrentSessionRevocable()).toBe(false); mockUser.current = function () { @@ -110,54 +110,54 @@ describe("ParseSession", () => { 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"); - expect(path).toBe("sessions/me"); + expect(method).toBe('GET'); + expect(path).toBe('sessions/me'); expect(options).toEqual({ - sessionToken: "abc123", + sessionToken: 'abc123', useMasterKey: true, }); return Promise.resolve({ - objectId: "session1", - sessionToken: "abc123", + objectId: 'session1', + sessionToken: 'abc123', }); }, ajax() {}, }); mockUser.currentAsync = function () { - return Promise.resolve(new mockUser("abc123")); + 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"); + expect(session.id).toBe('session1'); + expect(session.getSessionToken()).toBe('abc123'); done(); }); }); - it("cannot get current session without current user", (done) => { + 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(); }); }); - it("can be cloned", () => { + it('can be cloned', () => { const s = ParseObject.fromJSON({ - className: "_Session", - sessionToken: "123abc", + className: '_Session', + sessionToken: '123abc', foo: 12, }); const clone = s.clone(); - expect(clone.className).toBe("_Session"); - expect(clone.get("foo")).toBe(12); - expect(clone.get("sessionToken")).toBe(undefined); + expect(clone.className).toBe('_Session'); + expect(clone.get('foo')).toBe(12); + expect(clone.get('sessionToken')).toBe(undefined); }); }); diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index 857272769..e081ecba7 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -7,355 +7,351 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../AnonymousUtils"); -jest.dontMock("../CoreManager"); -jest.dontMock("../CryptoController"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../isRevocableSession"); -jest.dontMock("../LocalDatastore"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../parseDate"); -jest.dontMock("../ParseError"); -jest.dontMock("../ParseObject"); -jest.dontMock("../ParseOp"); -jest.dontMock("../ParseUser"); -jest.dontMock("../promiseUtils"); -jest.dontMock("../RESTController"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../Storage"); -jest.dontMock("../StorageController.default"); -jest.dontMock("../TaskQueue"); -jest.dontMock("../unique"); -jest.dontMock("../UniqueInstanceStateController"); -jest.dontMock("crypto-js/aes"); -jest.dontMock("crypto-js/enc-utf8"); - -jest.mock("uuid/v4", () => { +jest.dontMock('../AnonymousUtils'); +jest.dontMock('../CoreManager'); +jest.dontMock('../CryptoController'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../isRevocableSession'); +jest.dontMock('../LocalDatastore'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../parseDate'); +jest.dontMock('../ParseError'); +jest.dontMock('../ParseObject'); +jest.dontMock('../ParseOp'); +jest.dontMock('../ParseUser'); +jest.dontMock('../promiseUtils'); +jest.dontMock('../RESTController'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../Storage'); +jest.dontMock('../StorageController.default'); +jest.dontMock('../TaskQueue'); +jest.dontMock('../unique'); +jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock('crypto-js/aes'); +jest.dontMock('crypto-js/enc-utf8'); + +jest.mock('uuid/v4', () => { let value = 0; return () => value++; }); -jest.dontMock("./test_helpers/mockXHR"); -jest.dontMock("./test_helpers/mockAsyncStorage"); - -const mockAsyncStorage = require("./test_helpers/mockAsyncStorage"); -const CoreManager = require("../CoreManager"); -const CryptoController = require("../CryptoController"); -const LocalDatastore = require("../LocalDatastore"); -const ParseObject = require("../ParseObject").default; -const ParseUser = require("../ParseUser").default; -const Storage = require("../Storage"); -const ParseError = require("../ParseError").default; -const AnonymousUtils = require("../AnonymousUtils").default; - -CoreManager.set("APPLICATION_ID", "A"); -CoreManager.set("JAVASCRIPT_KEY", "B"); +jest.dontMock('./test_helpers/mockXHR'); +jest.dontMock('./test_helpers/mockAsyncStorage'); + +const mockAsyncStorage = require('./test_helpers/mockAsyncStorage'); +const CoreManager = require('../CoreManager'); +const CryptoController = require('../CryptoController'); +const LocalDatastore = require('../LocalDatastore'); +const ParseObject = require('../ParseObject').default; +const ParseUser = require('../ParseUser').default; +const Storage = require('../Storage'); +const ParseError = require('../ParseError').default; +const AnonymousUtils = require('../AnonymousUtils').default; + +CoreManager.set('APPLICATION_ID', 'A'); +CoreManager.set('JAVASCRIPT_KEY', 'B'); CoreManager.setCryptoController(CryptoController); function flushPromises() { - return new Promise((resolve) => setImmediate(resolve)); + return new Promise(resolve => setImmediate(resolve)); } -describe("ParseUser", () => { +describe('ParseUser', () => { beforeEach(() => { ParseObject.enableSingleInstance(); LocalDatastore._clear(); }); - it("can be constructed with initial attributes", () => { + it('can be constructed with initial attributes', () => { let u = new ParseUser(); expect(u.isCurrent()).toBe(false); - expect(u.className).toBe("_User"); + expect(u.className).toBe('_User'); expect(u instanceof ParseObject).toBe(true); u = new ParseUser({ - username: "andrew", - password: "secret", + username: 'andrew', + password: 'secret', }); - expect(u.get("username")).toBe("andrew"); - expect(u.get("password")).toBe("secret"); + expect(u.get('username')).toBe('andrew'); + expect(u.get('password')).toBe('secret'); expect(function () { new ParseUser({ - $$$: "invalid", + $$$: 'invalid', }); }).toThrow("Can't create an invalid Parse User"); }); - it("exposes certain attributes through special setters and getters", () => { + it('exposes certain attributes through special setters and getters', () => { const u = ParseObject.fromJSON({ - className: "_User", - username: "user12", - email: "user12@parse.com", - sessionToken: "123abc", + className: '_User', + username: 'user12', + email: 'user12@parse.com', + sessionToken: '123abc', }); expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe("user12"); - expect(u.getEmail()).toBe("user12@parse.com"); - expect(u.getSessionToken()).toBe("123abc"); + expect(u.getUsername()).toBe('user12'); + expect(u.getEmail()).toBe('user12@parse.com'); + expect(u.getSessionToken()).toBe('123abc'); const u2 = new ParseUser(); - u2.setUsername("bono"); - u2.setEmail("bono@u2.com"); - expect(u2.getUsername()).toBe("bono"); - expect(u2.getEmail()).toBe("bono@u2.com"); + u2.setUsername('bono'); + u2.setEmail('bono@u2.com'); + expect(u2.getUsername()).toBe('bono'); + expect(u2.getEmail()).toBe('bono@u2.com'); }); - it("can handle invalid setters and getters", () => { + it('can handle invalid setters and getters', () => { const u = ParseObject.fromJSON({ - className: "_User", + className: '_User', username: 123, email: 456, sessionToken: 789, }); expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe(""); - expect(u.getEmail()).toBe(""); - expect(u.getSessionToken()).toBe(""); + expect(u.getUsername()).toBe(''); + expect(u.getEmail()).toBe(''); + expect(u.getSessionToken()).toBe(''); }); - it("can clone User objects", () => { + it('can clone User objects', () => { const u = ParseObject.fromJSON({ - className: "_User", - username: "user12", - email: "user12@parse.com", - sessionToken: "123abc", + className: '_User', + username: 'user12', + email: 'user12@parse.com', + sessionToken: '123abc', }); const clone = u.clone(); - expect(clone.className).toBe("_User"); - expect(clone.get("username")).toBe("user12"); - expect(clone.get("email")).toBe("user12@parse.com"); - expect(clone.get("sessionToken")).toBe(undefined); + expect(clone.className).toBe('_User'); + expect(clone.get('username')).toBe('user12'); + expect(clone.get('email')).toBe('user12@parse.com'); + expect(clone.get('sessionToken')).toBe(undefined); }); - it("can create a new instance of a User", () => { + it('can create a new instance of a User', () => { ParseObject.disableSingleInstance(); const o = ParseObject.fromJSON({ - className: "_User", - objectId: "U111", - username: "u111", - email: "u111@parse.com", - sesionToken: "1313", + className: '_User', + objectId: 'U111', + username: 'u111', + email: 'u111@parse.com', + sesionToken: '1313', }); let o2 = o.newInstance(); expect(o.id).toBe(o2.id); expect(o.className).toBe(o2.className); - expect(o.get("username")).toBe(o2.get("username")); - expect(o.get("sessionToken")).toBe(o2.get("sessionToken")); + expect(o.get('username')).toBe(o2.get('username')); + expect(o.get('sessionToken')).toBe(o2.get('sessionToken')); expect(o).not.toBe(o2); o.set({ admin: true }); - expect(o2.get("admin")).toBe(undefined); + expect(o2.get('admin')).toBe(undefined); o2 = o.newInstance(); - expect(o2.get("admin")).toBe(true); + expect(o2.get('admin')).toBe(true); ParseObject.enableSingleInstance(); }); - it("makes session tokens readonly", () => { + it('makes session tokens readonly', () => { const u = new ParseUser(); - expect(u.set.bind(u, "sessionToken", "token")).toThrow( - "Cannot modify readonly attribute: sessionToken" + expect(u.set.bind(u, 'sessionToken', 'token')).toThrow( + 'Cannot modify readonly attribute: sessionToken' ); }); - it("does not allow current user actions on node servers", () => { - expect(ParseUser.become.bind(null, "token")).toThrow( - "It is not memory-safe to become a user in a server environment" + it('does not allow current user actions on node servers', () => { + expect(ParseUser.become.bind(null, 'token')).toThrow( + 'It is not memory-safe to become a user in a server environment' ); }); - it("can sign up a new user", (done) => { + it('can sign up a new user', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("POST"); - expect(path).toBe("users"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('POST'); + expect(path).toBe('users'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid", + objectId: 'uid', }, 201 ); }, ajax() {}, }); - ParseUser.signUp(null, "password").then( + 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." - ); + error => { + expect(error.message).toBe('Cannot sign up user with an empty username.'); } ); - ParseUser.signUp("username").then( + 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." - ); + 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); + ParseUser.signUp('username', 'password').then(u => { + expect(u.id).toBe('uid'); + expect(u.get('username')).toBe('username'); + expect(u.get('password')).toBe(undefined); expect(u.isCurrent()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe("uid"); - expect(current.getUsername()).toBe("username"); - expect(current.get("password")).toBe(undefined); + expect(current.id).toBe('uid'); + expect(current.getUsername()).toBe('username'); + expect(current.get('password')).toBe(undefined); done(); }); }); - it("can log in as a user", (done) => { + it('can log in as a user', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("GET"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - ParseUser.logIn("username", "password").then((u) => { - expect(u.id).toBe("uid2"); - expect(u.getSessionToken()).toBe("123abc"); + ParseUser.logIn('username', 'password').then(u => { + expect(u.id).toBe('uid2'); + expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe("uid2"); + expect(current.id).toBe('uid2'); expect(current.authenticated()).toBe(true); done(); }); }); - it("can log in as a user with options", async () => { + it('can log in as a user with options', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); expect(options.useMasterKey).toBe(true); - expect(options.installationId).toBe("installation1234"); + expect(options.installationId).toBe('installation1234'); return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - const user = await ParseUser.logIn("username", "password", { + const user = await ParseUser.logIn('username', 'password', { useMasterKey: true, - installationId: "installation1234", + installationId: 'installation1234', }); - expect(user.id).toBe("uid2"); + 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({ request(method, path, body) { - expect(method).toBe("POST"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('POST'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - ParseUser.logIn("username", "password", { usePost: true }).then((u) => { - expect(u.id).toBe("uid2"); - expect(u.getSessionToken()).toBe("123abc"); + ParseUser.logIn('username', 'password', { usePost: true }).then(u => { + expect(u.id).toBe('uid2'); + expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); expect(ParseUser.current()).toBe(u); ParseUser._clearCache(); const current = ParseUser.current(); expect(current instanceof ParseUser).toBe(true); - expect(current.id).toBe("uid2"); + expect(current.id).toBe('uid2'); expect(current.authenticated()).toBe(true); done(); }); }); - 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) => { + ParseUser.logIn({}, 'password') + .then(null, err => { expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe("Username must be a string."); + expect(err.message).toBe('Username must be a string.'); - return ParseUser.logIn("username", {}); + return ParseUser.logIn('username', {}); }) - .then(null, (err) => { + .then(null, err => { expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe("Password must be a string."); + 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({ request(method, path, body) { - expect(method).toBe("GET"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -363,32 +359,32 @@ describe("ParseUser", () => { ajax() {}, }); const u = new ParseUser({ - username: "username", - password: "password", + username: 'username', + password: 'password', }); - u.set("count", 5); + u.set('count', 5); u.logIn().then(() => { - expect(u.id).toBe("uid3"); - expect(u.dirtyKeys()).toEqual(["count"]); - expect(u.get("count")).toBe(5); + expect(u.id).toBe('uid3'); + expect(u.dirtyKeys()).toEqual(['count']); + expect(u.get('count')).toBe(5); done(); }); }); - 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({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("users/me"); - expect(options.sessionToken).toBe("123abc"); + expect(method).toBe('GET'); + expect(path).toBe('users/me'); + expect(options.sessionToken).toBe('123abc'); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -396,30 +392,30 @@ describe("ParseUser", () => { ajax() {}, }); - ParseUser.become("123abc").then((u) => { - expect(u.id).toBe("uid3"); + ParseUser.become('123abc').then(u => { + expect(u.id).toBe('uid3'); expect(u.isCurrent()).toBe(true); expect(u.existed()).toBe(true); done(); }); }); - it("can become a user with async storage", async () => { + it('can become a user with async storage', async () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("users/me"); - expect(options.sessionToken).toBe("123abc"); + expect(method).toBe('GET'); + expect(path).toBe('users/me'); + expect(options.sessionToken).toBe('123abc'); expect(options.useMasterKey).toBe(true); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -427,14 +423,14 @@ describe("ParseUser", () => { ajax() {}, }); - const u = await ParseUser.become("123abc", { useMasterKey: true }); - expect(u.id).toBe("uid3"); + const u = await ParseUser.become('123abc', { useMasterKey: true }); + expect(u.id).toBe('uid3'); expect(u.isCurrent()).toBe(true); expect(u.existed()).toBe(true); CoreManager.setStorageController(currentStorage); }); - it("cannot get synchronous current user with async storage", async () => { + it('cannot get synchronous current user with async storage', async () => { const StorageController = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); ParseUser.enableUnsafeCurrentUser(); @@ -442,97 +438,97 @@ describe("ParseUser", () => { expect(() => { ParseUser.current(); }).toThrow( - "Cannot call currentUser() when using a platform with an async storage system. Call currentUserAsync() instead." + '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 () => { + it('can hydrate a user with sessionToken in server environment', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); const user = await ParseUser.hydrate({ - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }); - expect(user.id).toBe("uid3"); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(true); expect(user.existed()).toBe(true); }); - it("can hydrate a user with sessionToken in non server environment", async () => { + it('can hydrate a user with sessionToken in non server environment', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); const user = await ParseUser.hydrate({ - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }); - expect(user.id).toBe("uid3"); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can hydrate a user without sessionToken", async () => { + it('can hydrate a user without sessionToken', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); await ParseUser.logOut(); const user = await ParseUser.hydrate({ - objectId: "uid3", - username: "username", + objectId: 'uid3', + username: 'username', }); - expect(user.id).toBe("uid3"); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can send a password reset request", () => { + it('can send a password reset request', () => { CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("POST"); - expect(path).toBe("requestPasswordReset"); - expect(body).toEqual({ email: "me@parse.com" }); + expect(method).toBe('POST'); + expect(path).toBe('requestPasswordReset'); + expect(body).toEqual({ email: 'me@parse.com' }); return Promise.resolve({}, 200); }, ajax() {}, }); - ParseUser.requestPasswordReset("me@parse.com"); + ParseUser.requestPasswordReset('me@parse.com'); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("POST"); - expect(path).toBe("requestPasswordReset"); - expect(body).toEqual({ email: "me@parse.com" }); + expect(method).toBe('POST'); + expect(path).toBe('requestPasswordReset'); + expect(body).toEqual({ email: 'me@parse.com' }); expect(options.useMasterKey).toBe(true); return Promise.resolve({}, 200); }, ajax() {}, }); - ParseUser.requestPasswordReset("me@parse.com", { useMasterKey: true }); + 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", + objectId: 'uid5', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - ParseUser.logIn("username", "password") - .then((u) => { + ParseUser.logIn('username', 'password') + .then(u => { expect(ParseUser.current()).toBe(u); CoreManager.setRESTController({ request() { @@ -550,31 +546,31 @@ describe("ParseUser", () => { }); }); - 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", + objectId: 'uid6', + username: 'username', + sessionToken: 'r:123abc', }, 200 ); }, ajax() {}, }); - ParseUser.logIn("username", "password") - .then((u) => { + 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(method).toBe('POST'); + expect(path).toBe('logout'); expect(options).toEqual({ - sessionToken: "r:123abc", + sessionToken: 'r:123abc', }); return Promise.resolve({}, 200); }, @@ -588,7 +584,7 @@ describe("ParseUser", () => { }); }); - it("can get the current user asynchronously", (done) => { + it('can get the current user asynchronously', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); @@ -596,9 +592,9 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid6", - username: "username", - sessionToken: "r:123abc", + objectId: 'uid6', + username: 'username', + sessionToken: 'r:123abc', }, 200 ); @@ -607,91 +603,91 @@ describe("ParseUser", () => { }); ParseUser.currentAsync() - .then((u) => { + .then(u => { expect(u).toBe(null); - return ParseUser.logIn("username", "password"); + return ParseUser.logIn('username', 'password'); }) - .then((u) => { + .then(u => { expect(u instanceof ParseUser).toBe(true); return ParseUser.currentAsync(); }) - .then((u) => { + .then(u => { expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe("username"); - expect(u.id).toBe("uid6"); + expect(u.getUsername()).toBe('username'); + expect(u.id).toBe('uid6'); ParseUser.disableUnsafeCurrentUser(); return ParseUser.currentAsync(); }) - .then((u) => { + .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"); + const path = Storage.generatePath('currentUser'); Storage.setItem( path, JSON.stringify({ - _id: "abc", - _sessionToken: "12345", - objectId: "abc", - username: "bob", + _id: 'abc', + _sessionToken: '12345', + objectId: 'abc', + username: 'bob', count: 12, }) ); - ParseUser.currentAsync().then((u) => { + ParseUser.currentAsync().then(u => { expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe("bob"); - expect(u.id).toBe("abc"); - expect(u.getSessionToken()).toBe("12345"); + expect(u.getUsername()).toBe('bob'); + expect(u.id).toBe('abc'); + expect(u.getSessionToken()).toBe('12345'); ParseUser._clearCache(); const user = ParseUser.current(); expect(user instanceof ParseUser).toBe(true); - expect(user.getUsername()).toBe("bob"); - expect(user.id).toBe("abc"); - expect(user.getSessionToken()).toBe("12345"); + expect(user.getUsername()).toBe('bob'); + expect(user.id).toBe('abc'); + expect(user.getSessionToken()).toBe('12345'); done(); }); }); - 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"); + const path = Storage.generatePath('currentUser'); Storage.setItem( path, JSON.stringify({ - _id: "abc", - _sessionToken: "12345", - objectId: "SET", - username: "bob", + _id: 'abc', + _sessionToken: '12345', + objectId: 'SET', + username: 'bob', count: 12, }) ); - ParseUser.currentAsync().then((u) => { + ParseUser.currentAsync().then(u => { expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe("bob"); - expect(u.id).toBe("abc"); - expect(u.getSessionToken()).toBe("12345"); + expect(u.getUsername()).toBe('bob'); + expect(u.id).toBe('abc'); + expect(u.getSessionToken()).toBe('12345'); ParseUser._clearCache(); const user = ParseUser.current(); expect(user instanceof ParseUser).toBe(true); - expect(user.getUsername()).toBe("bob"); - expect(user.id).toBe("abc"); - expect(user.getSessionToken()).toBe("12345"); + expect(user.getUsername()).toBe('bob'); + expect(user.id).toBe('abc'); + expect(user.getSessionToken()).toBe('12345'); done(); }); }); - 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(); @@ -699,7 +695,7 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid5", + objectId: 'uid5', }, 201 ); @@ -707,8 +703,8 @@ describe("ParseUser", () => { ajax() {}, }); - ParseUser.signUp("updater", "password") - .then((u) => { + ParseUser.signUp('updater', 'password') + .then(u => { expect(u.isCurrent()).toBe(true); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -719,21 +715,21 @@ describe("ParseUser", () => { }); return u.save({ count: 12 }); }) - .then((u) => { + .then(u => { ParseUser._clearCache(); ParseObject._clearAllState(); expect(u.attributes).toEqual({}); - expect(u.get("count")).toBe(undefined); + expect(u.get('count')).toBe(undefined); return ParseUser.currentAsync(); }) - .then((current) => { - expect(current.id).toBe("uid5"); - expect(current.get("count")).toBe(12); + .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(); @@ -741,7 +737,7 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid9", + objectId: 'uid9', }, 201 ); @@ -749,8 +745,8 @@ describe("ParseUser", () => { ajax() {}, }); - ParseUser.signUp("destroyed", "password") - .then((u) => { + ParseUser.signUp('destroyed', 'password') + .then(u => { expect(u.isCurrent()).toBe(true); CoreManager.setRESTController({ request() { @@ -764,13 +760,13 @@ describe("ParseUser", () => { expect(ParseUser.current()).toBe(null); return ParseUser.currentAsync(); }) - .then((current) => { + .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(); @@ -778,7 +774,7 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid6", + objectId: 'uid6', }, 200 ); @@ -786,8 +782,8 @@ describe("ParseUser", () => { ajax() {}, }); - ParseUser.signUp("spot", "fetch") - .then((u) => { + ParseUser.signUp('spot', 'fetch') + .then(u => { expect(u.isCurrent()).toBe(true); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -803,21 +799,21 @@ describe("ParseUser", () => { }); return u.fetch(); }) - .then((u) => { + .then(u => { ParseUser._clearCache(); ParseObject._clearAllState(); expect(u.attributes).toEqual({}); - expect(u.get("count")).toBe(undefined); + expect(u.get('count')).toBe(undefined); return ParseUser.currentAsync(); }) - .then((current) => { - expect(current.id).toBe("uid6"); - expect(current.get("count")).toBe(15); + .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 () => { + it('updates the current user on disk when fetched with include', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); @@ -825,18 +821,18 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid6", + objectId: 'uid6', }, 200 ); }, ajax() {}, }); - const child = new ParseObject("TestObject"); - child.set("foo", "bar"); + const child = new ParseObject('TestObject'); + child.set('foo', 'bar'); await child.save(); - let u = await ParseUser.signUp("spot", "fetchWithInclude"); + let u = await ParseUser.signUp('spot', 'fetchWithInclude'); expect(u.isCurrent()).toBe(true); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -851,19 +847,19 @@ describe("ParseUser", () => { }, ajax() {}, }); - u = await u.fetchWithInclude("child"); + u = await u.fetchWithInclude('child'); ParseUser._clearCache(); ParseObject._clearAllState(); expect(u.attributes).toEqual({}); - expect(u.get("count")).toBe(undefined); + expect(u.get('count')).toBe(undefined); const current = await ParseUser.currentAsync(); - expect(current.id).toBe("uid6"); - expect(current.get("count")).toBe(15); - expect(current.get("child").foo).toBe("bar"); + expect(current.id).toBe('uid6'); + expect(current.get('count')).toBe(15); + expect(current.get('child').foo).toBe('bar'); }); - it("does not update non-auth user when fetched with include", async () => { + it('does not update non-auth user when fetched with include', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); @@ -871,18 +867,18 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid6", + objectId: 'uid6', }, 200 ); }, ajax() {}, }); - const child = new ParseObject("TestObject"); - child.set("foo", "bar"); + const child = new ParseObject('TestObject'); + child.set('foo', 'bar'); await child.save(); - const u = await ParseUser.signUp("spot", "fetchWithInclude"); + const u = await ParseUser.signUp('spot', 'fetchWithInclude'); await ParseUser.logOut(); expect(u.isCurrent()).toBe(false); ParseUser._clearCache(); @@ -898,15 +894,15 @@ describe("ParseUser", () => { }, ajax() {}, }); - const fetchedUser = await u.fetchWithInclude("child"); + const fetchedUser = await u.fetchWithInclude('child'); const current = await ParseUser.currentAsync(); expect(current).toBe(null); - expect(fetchedUser.get("count")).toBe(15); - expect(fetchedUser.get("child").foo).toBe("bar"); + expect(fetchedUser.get('count')).toBe(15); + 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(); @@ -914,7 +910,7 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid5", + objectId: 'uid5', }, 201 ); @@ -922,9 +918,9 @@ describe("ParseUser", () => { ajax() {}, }); - const path = Storage.generatePath("currentUser"); - ParseUser.signUp("temporary", "password") - .then((u) => { + 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(); @@ -944,19 +940,19 @@ describe("ParseUser", () => { }); }); - it("can retreive a user with sessionToken (me)", async () => { + it('can retreive a user with sessionToken (me)', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("users/me"); - expect(options.sessionToken).toBe("123abc"); + expect(method).toBe('GET'); + expect(path).toBe('users/me'); + expect(options.sessionToken).toBe('123abc'); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -964,26 +960,26 @@ describe("ParseUser", () => { ajax() {}, }); - const user = await ParseUser.me("123abc"); - expect(user.id).toBe("uid3"); + const user = await ParseUser.me('123abc'); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can retreive a user with sessionToken and masterKey(me)", async () => { + it('can retreive a user with sessionToken and masterKey(me)', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("GET"); - expect(path).toBe("users/me"); - expect(options.sessionToken).toBe("123abc"); + expect(method).toBe('GET'); + expect(path).toBe('users/me'); + expect(options.sessionToken).toBe('123abc'); expect(options.useMasterKey).toBe(true); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -991,13 +987,13 @@ describe("ParseUser", () => { ajax() {}, }); - const user = await ParseUser.me("123abc", { useMasterKey: true }); - expect(user.id).toBe("uid3"); + const user = await ParseUser.me('123abc', { useMasterKey: true }); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can logout user with sessionToken", async () => { + it('can logout user with sessionToken', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); @@ -1007,31 +1003,31 @@ describe("ParseUser", () => { }, ajax() {}, }; - jest.spyOn(RESTController, "request"); + jest.spyOn(RESTController, 'request'); CoreManager.setRESTController(RESTController); - await ParseUser.logOut({ sessionToken: "1234" }); + await ParseUser.logOut({ sessionToken: '1234' }); expect(RESTController.request).toHaveBeenCalledWith( - "POST", - "logout", + 'POST', + 'logout', {}, - { sessionToken: "1234" } + { 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(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, - "Another user is already linked to this facebook id." + 'Another user is already linked to this facebook id.' ); return Promise.reject(error); }, @@ -1041,8 +1037,8 @@ describe("ParseUser", () => { authenticate(options) { if (options.success) { options.success(this, { - id: "id", - access_token: "access_token", + id: 'id', + access_token: 'access_token', }); } }, @@ -1050,7 +1046,7 @@ describe("ParseUser", () => { restoreAuthentication() {}, getAuthType() { - return "test"; + return 'test'; }, deauthenticate() {}, @@ -1060,27 +1056,25 @@ describe("ParseUser", () => { () => { // Should not run }, - (error) => { + error => { expect(error.code).toBe(ParseError.ACCOUNT_ALREADY_LINKED); - expect(error.message).toBe( - "Another user is already linked to this facebook id." - ); + expect(error.message).toBe('Another user is already linked to this facebook id.'); done(); } ); }); - it("can sync anonymous user with current user", async () => { + it('can sync anonymous user with current user', async () => { const provider = AnonymousUtils._getAuthProvider(); - jest.spyOn(provider, "restoreAuthentication"); + jest.spyOn(provider, 'restoreAuthentication'); const object = new ParseUser(); - object.set("authData", provider.getAuthData()); + object.set('authData', provider.getAuthData()); - jest.spyOn(object, "isCurrent").mockImplementationOnce(() => true); + jest.spyOn(object, 'isCurrent').mockImplementationOnce(() => true); const spy = jest - .spyOn(ParseUser, "currentAsync") + .spyOn(ParseUser, 'currentAsync') .mockImplementationOnce(() => Promise.resolve(object)); ParseUser._registerAuthenticationProvider(provider); @@ -1092,18 +1086,18 @@ describe("ParseUser", () => { spy.mockRestore(); }); - it("can destroy anonymous user on logout", async () => { + it('can destroy anonymous user on logout', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid5", - sessionToken: "r:123abc", + objectId: 'uid5', + sessionToken: 'r:123abc', authData: { anonymous: { - id: "anonymousId", + id: 'anonymousId', }, }, }, @@ -1113,55 +1107,49 @@ describe("ParseUser", () => { ajax() {}, }); const user = await AnonymousUtils.logIn(); - jest.spyOn(user, "destroy"); + jest.spyOn(user, 'destroy'); ParseUser._setCurrentUserCache(user); await ParseUser.logOut(); expect(user.destroy).toHaveBeenCalledTimes(1); }); - it("can unlink", async () => { + it('can unlink', async () => { const provider = AnonymousUtils._getAuthProvider(); ParseUser._registerAuthenticationProvider(provider); const user = new ParseUser(); - jest.spyOn(user, "linkWith"); + jest.spyOn(user, 'linkWith'); user._unlinkFrom(provider); expect(user.linkWith).toHaveBeenCalledTimes(1); - expect(user.linkWith).toHaveBeenCalledWith( - provider, - { authData: null }, - undefined - ); + expect(user.linkWith).toHaveBeenCalledWith(provider, { authData: null }, undefined); }); - it("can unlink with options", async () => { + it('can unlink with options', async () => { 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); }); - it("can destroy anonymous user when login new user", async () => { + it('can destroy anonymous user when login new user', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid5", - sessionToken: "r:123abc", + objectId: 'uid5', + sessionToken: 'r:123abc', authData: { anonymous: { - id: "anonymousId", + id: 'anonymousId', }, }, }, @@ -1171,43 +1159,43 @@ describe("ParseUser", () => { ajax() {}, }); const user = await AnonymousUtils.logIn(); - jest.spyOn(user, "destroy"); + jest.spyOn(user, 'destroy'); ParseUser._setCurrentUserCache(user); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - await ParseUser.logIn("username", "password"); + await ParseUser.logIn('username', 'password'); expect(user.destroy).toHaveBeenCalledTimes(1); }); - it("strip anonymity when we set username", () => { + it('strip anonymity when we set username', () => { const user = new ParseUser(); const authData = { anonymous: { - id: "anonymousId", + id: 'anonymousId', }, }; - user.set("authData", authData); - expect(user.get("authData").anonymous.id).toBe("anonymousId"); + user.set('authData', authData); + expect(user.get('authData').anonymous.id).toBe('anonymousId'); // Set username should strip anonymous authData - user.setUsername("test"); - expect(user.getUsername()).toBe("test"); - expect(user.get("authData").anonymous).toBe(null); + user.setUsername('test'); + expect(user.getUsername()).toBe('test'); + 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(); @@ -1215,10 +1203,10 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uidfetch", - username: "temporary", + objectId: 'uidfetch', + username: 'temporary', number: 123, - sessionToken: "abc141", + sessionToken: 'abc141', }, 201 ); @@ -1226,42 +1214,40 @@ describe("ParseUser", () => { ajax() {}, }); - ParseUser.signUp("temporary", "password").then((u) => { - expect(u.getSessionToken()).toBe("abc141"); - expect(u.get("number")).toBe(123); + 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", + objectId: 'uidfetch', + className: '_User', + username: 'temporary', }, true ); - expect(u.getSessionToken()).toBe("abc141"); - expect(u2.getSessionToken()).toBe("abc141"); - expect(u.get("number")).toBe(undefined); - expect(u2.get("number")).toBe(undefined); + expect(u.getSessionToken()).toBe('abc141'); + expect(u2.getSessionToken()).toBe('abc141'); + expect(u.get('number')).toBe(undefined); + expect(u2.get('number')).toBe(undefined); done(); }); }); - it("can linkWith options", async () => { + it('can linkWith options', async () => { ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body, options) { - expect(options).toEqual( - expect.objectContaining({ useMasterKey: true }) - ); + expect(options).toEqual(expect.objectContaining({ useMasterKey: true })); return Promise.resolve( { - objectId: "uid5", - sessionToken: "r:123abc", + objectId: 'uid5', + sessionToken: 'r:123abc', authData: { test: { - id: "id", - access_token: "access_token", + id: 'id', + access_token: 'access_token', }, }, }, @@ -1274,14 +1260,14 @@ describe("ParseUser", () => { authenticate(options) { if (options.success) { options.success(this, { - id: "id", - access_token: "access_token", + id: 'id', + access_token: 'access_token', }); } }, restoreAuthentication() {}, getAuthType() { - return "test"; + return 'test'; }, deauthenticate() {}, }; @@ -1289,23 +1275,23 @@ describe("ParseUser", () => { 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 () => { + it('handle linkWith authentication failure', async () => { const provider = { authenticate(options) { if (options.error) { options.error(this, { - message: "authentication failed", + message: 'authentication failed', }); } }, restoreAuthentication() {}, getAuthType() { - return "test"; + return 'test'; }, deauthenticate() {}, }; @@ -1315,21 +1301,21 @@ 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'); } }); - it("can linkWith if no provider", async () => { + it('can linkWith if no provider', async () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid6", - sessionToken: "r:123abc", + objectId: 'uid6', + sessionToken: 'r:123abc', authData: { testProvider: { - id: "test", + id: 'test', }, }, }, @@ -1339,31 +1325,29 @@ describe("ParseUser", () => { ajax() {}, }); const user = new ParseUser(); - await user._linkWith("testProvider", { authData: { id: "test" } }); - expect(user.get("authData")).toEqual({ testProvider: { id: "test" } }); + await user._linkWith('testProvider', { authData: { id: 'test' } }); + expect(user.get('authData')).toEqual({ testProvider: { id: 'test' } }); - jest.spyOn(user, "linkWith"); + jest.spyOn(user, 'linkWith'); - await user._unlinkFrom("testProvider"); + await user._unlinkFrom('testProvider'); const authProvider = user.linkWith.mock.calls[0][0]; - expect(authProvider).toBe("testProvider"); + expect(authProvider).toBe('testProvider'); }); - it("cannot linkWith invalid authData", async () => { + it('cannot linkWith invalid authData', async () => { ParseUser._clearCache(); const user = new ParseUser(); - user.set("authData", 1234); + user.set('authData', 1234); try { - await user.linkWith("testProvider", { authData: { id: "test" } }); + await user.linkWith('testProvider', { authData: { id: 'test' } }); expect(false).toBe(true); } catch (e) { - expect(e.message).toBe( - "Invalid type: authData field should be an object" - ); + expect(e.message).toBe('Invalid type: authData field should be an object'); } }); - it("_synchronizeAuthData can unlink on failure to restore auth ", async () => { + it('_synchronizeAuthData can unlink on failure to restore auth ', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1372,53 +1356,53 @@ describe("ParseUser", () => { return false; }, getAuthType() { - return "test"; + return 'test'; }, }; const user = new ParseUser(); - user.id = "sync123"; - user.set("authData", { test: true }); + user.id = 'sync123'; + user.set('authData', { test: true }); ParseUser._setCurrentUserCache(user); - jest.spyOn(user, "_unlinkFrom"); + jest.spyOn(user, '_unlinkFrom'); user._synchronizeAuthData(provider); expect(user._unlinkFrom).toHaveBeenCalledTimes(1); }); - it("_isLinked", () => { + it('_isLinked', () => { const user = new ParseUser(); const provider = { - getAuthType: () => "customAuth", + getAuthType: () => 'customAuth', }; - user.set("authData", { customAuth: true }); + user.set('authData', { customAuth: true }); expect(user._isLinked(provider)).toBe(true); - user.set("authData", 1234); + user.set('authData', 1234); expect(user._isLinked(provider)).toBe(false); }); - it("_cleanupAuthData", () => { + it('_cleanupAuthData', () => { ParseUser.enableUnsafeCurrentUser(); const user = new ParseUser(); - user.id = "cleanupData1"; - user.set("authData", { toRemove: null, test: true }); + user.id = 'cleanupData1'; + user.set('authData', { toRemove: null, test: true }); user._cleanupAuthData(); - expect(user.get("authData")).toEqual({ toRemove: null, test: true }); + expect(user.get('authData')).toEqual({ toRemove: null, test: true }); ParseUser._setCurrentUserCache(user); user._cleanupAuthData(); - expect(user.get("authData")).toEqual({ test: true }); + expect(user.get('authData')).toEqual({ test: true }); - user.set("authData", 1234); + user.set('authData', 1234); user._cleanupAuthData(); - expect(user.get("authData")).toEqual(1234); + expect(user.get('authData')).toEqual(1234); }); - it("_logOutWith", () => { + it('_logOutWith', () => { const user = new ParseUser(); - user.id = "logout1234"; + user.id = 'logout1234'; const provider = { deauthenticate: jest.fn(), }; @@ -1430,19 +1414,19 @@ describe("ParseUser", () => { expect(provider.deauthenticate).toHaveBeenCalledTimes(1); }); - it("_logInWith", async () => { + it('_logInWith', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid10", - sessionToken: "r:123abc", + objectId: 'uid10', + sessionToken: 'r:123abc', authData: { test: { - id: "id", - access_token: "access_token", + id: 'id', + access_token: 'access_token', }, }, }, @@ -1455,14 +1439,14 @@ describe("ParseUser", () => { authenticate(options) { if (options.success) { options.success(this, { - id: "id", - access_token: "access_token", + id: 'id', + access_token: 'access_token', }); } }, restoreAuthentication() {}, getAuthType() { - return "test"; + return 'test'; }, deauthenticate() {}, }; @@ -1470,14 +1454,14 @@ describe("ParseUser", () => { const user = await ParseUser._logInWith(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("can encrypt user", async () => { - CoreManager.set("ENCRYPTED_USER", true); - CoreManager.set("ENCRYPTED_KEY", "hello"); + it('can encrypt user', async () => { + CoreManager.set('ENCRYPTED_USER', true); + CoreManager.set('ENCRYPTED_KEY', 'hello'); ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1485,54 +1469,54 @@ describe("ParseUser", () => { let u = null; CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("GET"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - u = await ParseUser.logIn("username", "password"); + u = await ParseUser.logIn('username', 'password'); // Clear cache to read from disk ParseUser._clearCache(); - expect(u.id).toBe("uid2"); - expect(u.getSessionToken()).toBe("123abc"); + expect(u.id).toBe('uid2'); + expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); const currentUser = ParseUser.current(); - expect(currentUser.id).toBe("uid2"); + expect(currentUser.id).toBe('uid2'); ParseUser._clearCache(); const currentUserAsync = await ParseUser.currentAsync(); - expect(currentUserAsync.id).toEqual("uid2"); + expect(currentUserAsync.id).toEqual('uid2'); - const path = Storage.generatePath("currentUser"); + const path = Storage.generatePath('currentUser'); const encryptedUser = Storage.getItem(path); const crypto = CoreManager.getCryptoController(); - const decryptedUser = crypto.decrypt(encryptedUser, "hello"); + const decryptedUser = crypto.decrypt(encryptedUser, 'hello'); expect(JSON.parse(decryptedUser).objectId).toBe(u.id); - CoreManager.set("ENCRYPTED_USER", false); - CoreManager.set("ENCRYPTED_KEY", null); + CoreManager.set('ENCRYPTED_USER', false); + CoreManager.set('ENCRYPTED_KEY', null); Storage._clear(); }); - it("can encrypt user with custom CryptoController", async () => { - CoreManager.set("ENCRYPTED_USER", true); - CoreManager.set("ENCRYPTED_KEY", "hello"); - const ENCRYPTED_DATA = "encryptedString"; + it('can encrypt user with custom CryptoController', async () => { + CoreManager.set('ENCRYPTED_USER', true); + CoreManager.set('ENCRYPTED_KEY', 'hello'); + const ENCRYPTED_DATA = 'encryptedString'; ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -1540,16 +1524,16 @@ describe("ParseUser", () => { let u = null; CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("GET"); - expect(path).toBe("login"); - expect(body.username).toBe("username"); - expect(body.password).toBe("password"); + expect(method).toBe('GET'); + expect(path).toBe('login'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -1558,49 +1542,49 @@ describe("ParseUser", () => { }); const CustomCrypto = { encrypt(obj, secretKey) { - expect(secretKey).toBe("hello"); + expect(secretKey).toBe('hello'); return ENCRYPTED_DATA; }, decrypt(encryptedText, secretKey) { expect(encryptedText).toBe(ENCRYPTED_DATA); - expect(secretKey).toBe("hello"); + expect(secretKey).toBe('hello'); return JSON.stringify(u.toJSON()); }, }; CoreManager.setCryptoController(CustomCrypto); - u = await ParseUser.logIn("username", "password"); + u = await ParseUser.logIn('username', 'password'); // Clear cache to read from disk ParseUser._clearCache(); - expect(u.id).toBe("uid2"); - expect(u.getSessionToken()).toBe("123abc"); + expect(u.id).toBe('uid2'); + expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); expect(u.authenticated()).toBe(true); - expect(ParseUser.current().id).toBe("uid2"); + expect(ParseUser.current().id).toBe('uid2'); - const path = Storage.generatePath("currentUser"); + const path = Storage.generatePath('currentUser'); const userStorage = Storage.getItem(path); expect(userStorage).toBe(ENCRYPTED_DATA); - CoreManager.set("ENCRYPTED_USER", false); - CoreManager.set("ENCRYPTED_KEY", null); + CoreManager.set('ENCRYPTED_USER', false); + CoreManager.set('ENCRYPTED_KEY', null); Storage._clear(); }); - it("can static signup a user with installationId", async () => { + it('can static signup a user with installationId', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); - const installationId = "12345678"; + const installationId = '12345678'; CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("POST"); - expect(path).toBe("users"); + expect(method).toBe('POST'); + expect(path).toBe('users'); expect(options.installationId).toBe(installationId); expect(options.useMasterKey).toBe(true); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -1608,29 +1592,29 @@ describe("ParseUser", () => { ajax() {}, }); - const user = await ParseUser.signUp("username", "password", null, { + const user = await ParseUser.signUp('username', 'password', null, { installationId, useMasterKey: true, }); - expect(user.id).toBe("uid3"); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can signup a user with installationId", async () => { + it('can signup a user with installationId', async () => { ParseUser.disableUnsafeCurrentUser(); ParseUser._clearCache(); - const installationId = "12345678"; + const installationId = '12345678'; CoreManager.setRESTController({ request(method, path, body, options) { - expect(method).toBe("POST"); - expect(path).toBe("users"); + expect(method).toBe('POST'); + expect(path).toBe('users'); expect(options.installationId).toBe(installationId); return Promise.resolve( { - objectId: "uid3", - username: "username", - sessionToken: "123abc", + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', }, 200 ); @@ -1639,47 +1623,47 @@ describe("ParseUser", () => { }); const user = new ParseUser(); - user.setUsername("name"); - user.setPassword("pass"); + user.setUsername('name'); + user.setPassword('pass'); await user.signUp(null, { installationId }); - expect(user.id).toBe("uid3"); + expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); }); - it("can verify user password", async () => { + it('can verify user password', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - const user = await ParseUser.verifyPassword("username", "password"); - expect(user.objectId).toBe("uid2"); - expect(user.username).toBe("username"); + const user = await ParseUser.verifyPassword('username', 'password'); + expect(user.objectId).toBe('uid2'); + expect(user.username).toBe('username'); const notStatic = new ParseUser(); - notStatic.setUsername("username"); - const userAgain = await notStatic.verifyPassword("password", { + notStatic.setUsername('username'); + const userAgain = await notStatic.verifyPassword('password', { useMasterKey: true, }); - expect(userAgain.objectId).toBe("uid2"); - expect(userAgain.username).toBe("username"); + expect(userAgain.objectId).toBe('uid2'); + expect(userAgain.username).toBe('username'); CoreManager.setRESTController({ request() { const parseError = new ParseError( ParseError.OBJECT_NOT_FOUND, - "Invalid username/password." + 'Invalid username/password.' ); return Promise.reject(parseError); }, @@ -1687,64 +1671,64 @@ describe("ParseUser", () => { }); try { - await ParseUser.verifyPassword("username", "wrong password"); + await ParseUser.verifyPassword('username', 'wrong password'); } catch (error) { expect(error.code).toBe(101); - expect(error.message).toBe("Invalid username/password."); + expect(error.message).toBe('Invalid username/password.'); } try { - await ParseUser.verifyPassword(null, "password"); + await ParseUser.verifyPassword(null, 'password'); } catch (error) { expect(error.code).toBe(-1); - expect(error.message).toBe("Username must be a string."); + expect(error.message).toBe('Username must be a string.'); } try { - await ParseUser.verifyPassword("username", null); + await ParseUser.verifyPassword('username', null); } catch (error) { expect(error.code).toBe(-1); - expect(error.message).toBe("Password must be a string."); + expect(error.message).toBe('Password must be a string.'); } }); - it("can send an email verification request", () => { + it('can send an email verification request', () => { CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe("POST"); - expect(path).toBe("verificationEmailRequest"); - expect(body).toEqual({ email: "me@parse.com" }); + expect(method).toBe('POST'); + expect(path).toBe('verificationEmailRequest'); + expect(body).toEqual({ email: 'me@parse.com' }); return Promise.resolve({}, 200); }, 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(method).toBe('POST'); + expect(path).toBe('verificationEmailRequest'); + expect(body).toEqual({ email: 'me@parse.com' }); expect(options.useMasterKey).toBe(true); return Promise.resolve({}, 200); }, ajax() {}, }); - ParseUser.requestEmailVerification("me@parse.com", { useMasterKey: true }); + ParseUser.requestEmailVerification('me@parse.com', { useMasterKey: true }); }); - it("allowCustomUserClass", () => { - expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(true); + it('allowCustomUserClass', () => { + expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(true); ParseUser.allowCustomUserClass(true); - expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(false); + expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(false); ParseUser.allowCustomUserClass(false); - expect(CoreManager.get("PERFORM_USER_REWRITE")).toBe(true); + expect(CoreManager.get('PERFORM_USER_REWRITE')).toBe(true); }); - it("enableRevocableSession", async () => { + it('enableRevocableSession', async () => { const result = await ParseUser.enableRevocableSession(); - expect(CoreManager.get("FORCE_REVOCABLE_SESSION")).toBe(true); + expect(CoreManager.get('FORCE_REVOCABLE_SESSION')).toBe(true); expect(result).toBeUndefined(); ParseUser.enableUnsafeCurrentUser(); @@ -1753,27 +1737,27 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - const user = await ParseUser.logIn("username", "password"); - jest.spyOn(user, "_upgradeToRevocableSession"); + const user = await ParseUser.logIn('username', 'password'); + jest.spyOn(user, '_upgradeToRevocableSession'); await ParseUser.enableRevocableSession({ useMasterKey: true }); expect(user._upgradeToRevocableSession).toHaveBeenCalled(); }); - it("upgradeToRevocableSession", async () => { + it('upgradeToRevocableSession', async () => { try { const unsavedUser = new ParseUser(); await unsavedUser._upgradeToRevocableSession(); } catch (e) { - expect(e.message).toBe("Cannot upgrade a user with no session token"); + expect(e.message).toBe('Cannot upgrade a user with no session token'); } ParseUser.disableUnsafeCurrentUser(); @@ -1782,27 +1766,27 @@ describe("ParseUser", () => { request() { return Promise.resolve( { - objectId: "uid2", - username: "username", - sessionToken: "123abc", + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', }, 200 ); }, ajax() {}, }); - const user = await ParseUser.logIn("username", "password"); + const user = await ParseUser.logIn('username', 'password'); const upgradedUser = await user._upgradeToRevocableSession(); expect(user).toEqual(upgradedUser); }); - it("extend", () => { + it('extend', () => { let CustomUser = ParseUser.extend(); expect(CustomUser instanceof ParseUser); CustomUser = ParseUser.extend( - { test: true, className: "Item" }, - { test: false, className: "Item" } + { test: true, className: 'Item' }, + { test: false, className: 'Item' } ); expect(CustomUser instanceof ParseUser); diff --git a/src/__tests__/Push-test.js b/src/__tests__/Push-test.js index 91c954d24..7db8014ee 100644 --- a/src/__tests__/Push-test.js +++ b/src/__tests__/Push-test.js @@ -7,9 +7,9 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../CoreManager"); -jest.dontMock("../Push"); -jest.dontMock("./test_helpers/asyncHelper"); +jest.dontMock('../CoreManager'); +jest.dontMock('../Push'); +jest.dontMock('./test_helpers/asyncHelper'); const mockQuery = function () { this.where = {}; @@ -21,15 +21,15 @@ mockQuery.prototype = { }; }, }; -jest.setMock("../ParseQuery", mockQuery); +jest.setMock('../ParseQuery', mockQuery); -const CoreManager = require("../CoreManager"); -const ParseQuery = require("../ParseQuery"); -const Push = require("../Push"); +const CoreManager = require('../CoreManager'); +const ParseQuery = require('../ParseQuery'); +const Push = require('../Push'); const defaultController = CoreManager.getPushController(); -describe("Push", () => { +describe('Push', () => { beforeEach(() => { CoreManager.setPushController({ send(data) { @@ -39,62 +39,62 @@ describe("Push", () => { }); }); - 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) => { + }).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) => { - expect(data.push_time).toBe("2015-02-01T00:00:00.000Z"); + }).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) => { - expect(data.push_time).toBe("2015-02-01T00:00:00.000"); + 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) => { - expect(data.expiration_time).toBe("2015-02-01T00:00:00.000Z"); + }).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", () => { + 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."); + ).toThrow('expiration_time and expiration_interval cannot both be set.'); }); }); -describe("PushController", () => { - it("forwards data along", () => { +describe('PushController', () => { + it('forwards data along', () => { CoreManager.setPushController(defaultController); const request = jest.fn().mockReturnValue({ _thenRunCallbacks() { @@ -117,9 +117,9 @@ describe("PushController", () => { } ); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ - "POST", - "push", - { push_time: "2015-02-01T00:00:00.000Z" }, + 'POST', + 'push', + { push_time: '2015-02-01T00:00:00.000Z' }, { useMasterKey: true }, ]); }); diff --git a/src/__tests__/RESTController-test.js b/src/__tests__/RESTController-test.js index 62917ba6c..cc6ffa8b2 100644 --- a/src/__tests__/RESTController-test.js +++ b/src/__tests__/RESTController-test.js @@ -9,41 +9,41 @@ jest.autoMockOff(); jest.useFakeTimers(); -jest.mock("uuid/v4", () => { +jest.mock('uuid/v4', () => { let value = 1000; return () => (value++).toString(); }); -const CoreManager = require("../CoreManager"); -const RESTController = require("../RESTController"); -const mockXHR = require("./test_helpers/mockXHR"); -const mockWeChat = require("./test_helpers/mockWeChat"); +const CoreManager = require('../CoreManager'); +const RESTController = require('../RESTController'); +const mockXHR = require('./test_helpers/mockXHR'); +const mockWeChat = require('./test_helpers/mockWeChat'); global.wx = mockWeChat; CoreManager.setInstallationController({ currentInstallationId() { - return Promise.resolve("iid"); + return Promise.resolve('iid'); }, }); -CoreManager.set("APPLICATION_ID", "A"); -CoreManager.set("JAVASCRIPT_KEY", "B"); -CoreManager.set("VERSION", "V"); +CoreManager.set('APPLICATION_ID', 'A'); +CoreManager.set('JAVASCRIPT_KEY', 'B'); +CoreManager.set('VERSION', 'V'); function flushPromises() { - return new Promise((resolve) => setImmediate(resolve)); + return new Promise(resolve => setImmediate(resolve)); } -describe("RESTController", () => { - it("throws if there is no XHR implementation", () => { +describe('RESTController', () => { + it('throws if there is no XHR implementation', () => { RESTController._setXHR(null); expect(RESTController._getXHR()).toBe(null); - expect(RESTController.ajax.bind(null, "GET", "users/me", {})).toThrow( - "Cannot make a request: No definition of XMLHttpRequest was found." + expect(RESTController.ajax.bind(null, 'GET', 'users/me', {})).toThrow( + 'Cannot make a request: No definition of XMLHttpRequest was found.' ); }); - it("opens a XHR with the correct verb and headers", () => { + it('opens a XHR with the correct verb and headers', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -52,40 +52,26 @@ describe("RESTController", () => { 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]); + 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.send.mock.calls[0][0]).toEqual({}); }); - 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 }) => { + 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); done(); }); }); - it("retries on 5XX errors", (done) => { + it('retries on 5XX errors', done => { RESTController._setXHR( - mockXHR([ - { status: 500 }, - { status: 500 }, - { status: 200, response: { success: true } }, - ]) + mockXHR([{ status: 500 }, { status: 500 }, { status: 200, response: { success: true } }]) ); - RESTController.ajax("POST", "users", {}).then(({ response, status }) => { + RESTController.ajax('POST', 'users', {}).then(({ response, status }) => { expect(response).toEqual({ success: true }); expect(status).toBe(200); done(); @@ -93,50 +79,34 @@ describe("RESTController", () => { jest.runAllTimers(); }); - it("retries on connection failure", (done) => { + it('retries on connection failure', done => { RESTController._setXHR( - mockXHR([ - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - ]) + 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"); + 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) => { + it('returns a connection error on network failure', async done => { RESTController._setXHR( - mockXHR([ - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - ]) + 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)); + 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) => { + it('aborts after too many failures', async done => { RESTController._setXHR( mockXHR([ { status: 500 }, @@ -147,24 +117,24 @@ describe("RESTController", () => { { status: 200, response: { success: true } }, ]) ); - RESTController.ajax("POST", "users", {}).then(null, (xhr) => { + 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(); }); jest.runAllTimers(); }); - it("can make formal JSON requests", async () => { + it('can make formal JSON requests', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -173,99 +143,83 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request( - "GET", - "classes/MyObject", - {}, - { sessionToken: "1234" } - ); + RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234' }); await flushPromises(); expect(xhr.open.mock.calls[0]).toEqual([ - "POST", - "https://api.parse.com/1/classes/MyObject", + 'POST', + 'https://api.parse.com/1/classes/MyObject', true, ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "iid", - _SessionToken: "1234", + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: 'iid', + _SessionToken: '1234', }); }); - it("handles request errors", (done) => { + it('handles request errors', done => { RESTController._setXHR( mockXHR([ { status: 400, response: { code: -1, - error: "Something bad", + error: 'Something bad', }, }, ]) ); - RESTController.request("GET", "classes/MyObject", {}, {}).then( - null, - (error) => { - expect(error.code).toBe(-1); - expect(error.message).toBe("Something bad"); - done(); - } - ); + 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) => { + it('handles invalid responses', done => { const XHR = function () {}; XHR.prototype = { open: function () {}, setRequestHeader: function () {}, send: function () { this.status = 200; - this.responseText = "{"; + 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) => { + it('handles invalid errors', done => { const XHR = function () {}; XHR.prototype = { open: function () {}, setRequestHeader: function () {}, send: function () { this.status = 400; - this.responseText = "{"; + 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 () => { + it('handles x-parse-job-status-id header', async () => { const XHR = function () {}; XHR.prototype = { open: function () {}, @@ -275,25 +229,20 @@ describe("RESTController", () => { }, send: function () { this.status = 200; - this.responseText = "{}"; + this.responseText = '{}'; this.readyState = 4; this.onreadystatechange(); }, getAllResponseHeaders: function () { - return "x-parse-job-status-id: 1234"; + 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 () => { + it('handles invalid header', async () => { const XHR = function () {}; XHR.prototype = { open: function () {}, @@ -312,18 +261,13 @@ describe("RESTController", () => { }, }; RESTController._setXHR(XHR); - const response = await RESTController.request( - "GET", - "classes/MyObject", - {}, - {} - ); - expect(response.result).toBe("hello"); + 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]; + it('idempotency - sends requestId header', async () => { + CoreManager.set('IDEMPOTENCY', true); + const requestIdHeader = header => 'X-Parse-Request-Id' === header[0]; const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -332,53 +276,43 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request("POST", "classes/MyObject", {}, {}); + RESTController.request('POST', 'classes/MyObject', {}, {}); await flushPromises(); expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual([ - ["X-Parse-Request-Id", "1000"], + ['X-Parse-Request-Id', '1000'], ]); xhr.setRequestHeader.mockClear(); - RESTController.request("PUT", "classes/MyObject", {}, {}); + RESTController.request('PUT', 'classes/MyObject', {}, {}); await flushPromises(); expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual([ - ["X-Parse-Request-Id", "1001"], + ['X-Parse-Request-Id', '1001'], ]); - CoreManager.set("IDEMPOTENCY", false); + CoreManager.set('IDEMPOTENCY', false); }); - it("idempotency - handle requestId on network retries", (done) => { - CoreManager.set("IDEMPOTENCY", true); + 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.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(); - expect(requestIdHeaders.length).toBe(3); - expect(response).toEqual({ success: true }); - expect(status).toBe(200); - done(); - } + 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(); + expect(requestIdHeaders.length).toBe(3); + expect(response).toEqual({ success: true }); + expect(status).toBe(200); + done(); + }); jest.runAllTimers(); - CoreManager.set("IDEMPOTENCY", false); + CoreManager.set('IDEMPOTENCY', false); }); - it("idempotency - should properly handle url method not POST / PUT", () => { - CoreManager.set("IDEMPOTENCY", true); + it('idempotency - should properly handle url method not POST / PUT', () => { + CoreManager.set('IDEMPOTENCY', true); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -387,15 +321,15 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.ajax("GET", "users/me", {}, {}); + RESTController.ajax('GET', 'users/me', {}, {}); const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter( - (header) => "X-Parse-Request-Id" === header[0] + header => 'X-Parse-Request-Id' === header[0] ); expect(requestIdHeaders.length).toBe(0); - CoreManager.set("IDEMPOTENCY", false); + CoreManager.set('IDEMPOTENCY', false); }); - it("handles aborted requests", (done) => { + it('handles aborted requests', done => { const XHR = function () {}; XHR.prototype = { open: function () {}, @@ -409,15 +343,15 @@ describe("RESTController", () => { }, }; RESTController._setXHR(XHR); - RESTController.request("GET", "classes/MyObject", {}, {}).then(() => { + RESTController.request('GET', 'classes/MyObject', {}, {}).then(() => { done(); }); }); - it("attaches the session token of the current user", async () => { + it('attaches the session token of the current user', async () => { CoreManager.setUserController({ currentUserAsync() { - return Promise.resolve({ getSessionToken: () => "5678" }); + return Promise.resolve({ getSessionToken: () => '5678' }); }, setCurrentUser() {}, currentUser() {}, @@ -441,20 +375,20 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request("GET", "classes/MyObject", {}, {}); + RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "iid", - _SessionToken: "5678", - }); - CoreManager.set("UserController", undefined); // Clean up + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: 'iid', + _SessionToken: '5678', + }); + CoreManager.set('UserController', undefined); // Clean up }); - it("attaches no session token when there is no current user", async () => { + it('attaches no session token when there is no current user', async () => { CoreManager.setUserController({ currentUserAsync() { return Promise.resolve(null); @@ -481,20 +415,20 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request("GET", "classes/MyObject", {}, {}); + RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "iid", + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: 'iid', }); - CoreManager.set("UserController", undefined); // Clean up + CoreManager.set('UserController', undefined); // Clean up }); - it("sends the revocable session upgrade header when the config flag is set", async () => { - CoreManager.set("FORCE_REVOCABLE_SESSION", true); + it('sends the revocable session upgrade header when the config flag is set', async () => { + CoreManager.set('FORCE_REVOCABLE_SESSION', true); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -503,22 +437,22 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request("GET", "classes/MyObject", {}, {}); + RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); xhr.onreadystatechange(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "iid", - _RevocableSession: "1", - }); - CoreManager.set("FORCE_REVOCABLE_SESSION", false); // Clean up + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: 'iid', + _RevocableSession: '1', + }); + CoreManager.set('FORCE_REVOCABLE_SESSION', false); // Clean up }); - it("sends the master key when requested", async () => { - CoreManager.set("MASTER_KEY", "M"); + it('sends the master key when requested', async () => { + CoreManager.set('MASTER_KEY', 'M'); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -527,37 +461,28 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request( - "GET", - "classes/MyObject", - {}, - { useMasterKey: true } - ); + RESTController.request('GET', 'classes/MyObject', {}, { useMasterKey: true }); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _MasterKey: "M", - _ClientVersion: "V", - _InstallationId: "iid", + _method: 'GET', + _ApplicationId: 'A', + _MasterKey: 'M', + _ClientVersion: 'V', + _InstallationId: 'iid', }); }); - 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", () => { - CoreManager.set("MASTER_KEY", undefined); + it('throws when attempted to use an unprovided master key', () => { + CoreManager.set('MASTER_KEY', undefined); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -567,19 +492,14 @@ describe("RESTController", () => { return xhr; }); expect(function () { - RESTController.request( - "GET", - "classes/MyObject", - {}, - { useMasterKey: true } - ); - }).toThrow("Cannot use the Master Key, it has not been provided."); + RESTController.request('GET', 'classes/MyObject', {}, { useMasterKey: true }); + }).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]; + 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 xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -588,16 +508,16 @@ describe("RESTController", () => { RESTController._setXHR(function () { return xhr; }); - RESTController.request("GET", "classes/MyObject", {}, {}); + RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); expect(xhr.setRequestHeader.mock.calls.filter(credentialsHeader)).toEqual([ - ["Authorization", "Bearer some_random_token"], + ['Authorization', 'Bearer some_random_token'], ]); - CoreManager.set("SERVER_AUTH_TYPE", null); - CoreManager.set("SERVER_AUTH_TOKEN", null); + 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, @@ -610,15 +530,15 @@ describe("RESTController", () => { const options = { progress: function () {}, }; - jest.spyOn(options, "progress"); + jest.spyOn(options, 'progress'); - RESTController.ajax("POST", "files/upload.txt", {}, {}, options).then( + RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then( ({ response, status }) => { expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { - type: "download", + type: 'download', }); expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { - type: "upload", + type: 'upload', }); expect(response).toEqual({ success: true }); expect(status).toBe(200); @@ -627,7 +547,7 @@ describe("RESTController", () => { ); }); - 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, @@ -640,12 +560,12 @@ describe("RESTController", () => { const options = { progress: function () {}, }; - jest.spyOn(options, "progress"); + jest.spyOn(options, 'progress'); - RESTController.ajax("POST", "files/upload.txt", {}, {}, options).then( + RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then( ({ response, status }) => { expect(options.progress).toHaveBeenCalledWith(null, null, null, { - type: "upload", + type: 'upload', }); expect(response).toEqual({ success: true }); expect(status).toBe(200); @@ -654,8 +574,8 @@ describe("RESTController", () => { ); }); - it("opens a XHR with the custom headers", () => { - CoreManager.set("REQUEST_HEADERS", { "Cache-Control": "max-age=3600" }); + it('opens a XHR with the custom headers', () => { + CoreManager.set('REQUEST_HEADERS', { 'Cache-Control': 'max-age=3600' }); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -664,22 +584,14 @@ describe("RESTController", () => { 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]); + 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.send.mock.calls[0][0]).toEqual({}); - CoreManager.set("REQUEST_HEADERS", {}); + CoreManager.set('REQUEST_HEADERS', {}); }); - it("can handle installationId option", async () => { + it('can handle installationId option', async () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), @@ -689,79 +601,74 @@ describe("RESTController", () => { return xhr; }); RESTController.request( - "GET", - "classes/MyObject", + 'GET', + 'classes/MyObject', {}, - { sessionToken: "1234", installationId: "5678" } + { sessionToken: '1234', installationId: '5678' } ); await flushPromises(); expect(xhr.open.mock.calls[0]).toEqual([ - "POST", - "https://api.parse.com/1/classes/MyObject", + 'POST', + 'https://api.parse.com/1/classes/MyObject', true, ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "5678", - _SessionToken: "1234", + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: '5678', + _SessionToken: '1234', }); }); - it("can handle wechat request", async () => { - const XHR = require("../Xhr.weapp"); + it('can handle wechat request', async () => { + const XHR = require('../Xhr.weapp'); const xhr = new XHR(); - jest.spyOn(xhr, "open"); - jest.spyOn(xhr, "send"); + jest.spyOn(xhr, 'open'); + jest.spyOn(xhr, 'send'); RESTController._setXHR(function () { return xhr; }); RESTController.request( - "GET", - "classes/MyObject", + 'GET', + 'classes/MyObject', {}, - { sessionToken: "1234", installationId: "5678" } + { sessionToken: '1234', installationId: '5678' } ); await flushPromises(); expect(xhr.open.mock.calls[0]).toEqual([ - "POST", - "https://api.parse.com/1/classes/MyObject", + 'POST', + 'https://api.parse.com/1/classes/MyObject', true, ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ - _method: "GET", - _ApplicationId: "A", - _JavaScriptKey: "B", - _ClientVersion: "V", - _InstallationId: "5678", - _SessionToken: "1234", + _method: 'GET', + _ApplicationId: 'A', + _JavaScriptKey: 'B', + _ClientVersion: 'V', + _InstallationId: '5678', + _SessionToken: '1234', }); }); - it("can handle wechat ajax", async () => { - const XHR = require("../Xhr.weapp"); + it('can handle wechat ajax', async () => { + const XHR = require('../Xhr.weapp'); const xhr = new XHR(); - jest.spyOn(xhr, "open"); - jest.spyOn(xhr, "send"); - jest.spyOn(xhr, "setRequestHeader"); + jest.spyOn(xhr, 'open'); + jest.spyOn(xhr, 'send'); + jest.spyOn(xhr, 'setRequestHeader'); 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]); + 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.send.mock.calls[0][0]).toEqual({}); xhr.responseHeader = headers; - expect(xhr.getAllResponseHeaders().includes("X-Parse-Session-Token")).toBe( - true - ); - expect(xhr.getResponseHeader("X-Parse-Session-Token")).toBe("123"); + expect(xhr.getAllResponseHeaders().includes('X-Parse-Session-Token')).toBe(true); + expect(xhr.getResponseHeader('X-Parse-Session-Token')).toBe('123'); xhr.abort(); xhr.abort(); }); diff --git a/src/__tests__/SingleInstanceStateController-test.js b/src/__tests__/SingleInstanceStateController-test.js index 3c1021bc1..4de1c1f13 100644 --- a/src/__tests__/SingleInstanceStateController-test.js +++ b/src/__tests__/SingleInstanceStateController-test.js @@ -7,70 +7,70 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseOp"); -jest.dontMock("../promiseUtils"); -jest.dontMock("../SingleInstanceStateController"); -jest.dontMock("../TaskQueue"); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseOp'); +jest.dontMock('../promiseUtils'); +jest.dontMock('../SingleInstanceStateController'); +jest.dontMock('../TaskQueue'); const mockObject = function () {}; mockObject.registerSubclass = function () {}; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); jest.useFakeTimers(); -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParseOps = require("../ParseOp"); -const SingleInstanceStateController = require("../SingleInstanceStateController"); -const TaskQueue = require("../TaskQueue"); +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseOps = require('../ParseOp'); +const SingleInstanceStateController = require('../SingleInstanceStateController'); +const TaskQueue = require('../TaskQueue'); -describe("SingleInstanceStateController", () => { - it("returns null state for an unknown object", () => { +describe('SingleInstanceStateController', () => { + it('returns null state for an unknown object', () => { expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "someId", + className: 'someClass', + id: 'someId', }) ).toBe(null); }); - it("returns empty data for an unknown object", () => { + it('returns empty data for an unknown object', () => { expect( SingleInstanceStateController.getServerData({ - className: "someClass", - id: "someId", + className: 'someClass', + id: 'someId', }) ).toEqual({}); }); - it("returns an empty op queue for an unknown object", () => { + it('returns an empty op queue for an unknown object', () => { expect( SingleInstanceStateController.getPendingOps({ - className: "someClass", - id: "someId", + className: 'someClass', + id: 'someId', }) ).toEqual([{}]); }); - it("initializes server data when setting state", () => { + it('initializes server data when setting state', () => { expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "A", + className: 'someClass', + id: 'A', }) ).toBe(null); SingleInstanceStateController.setServerData( - { className: "someClass", id: "A" }, + { className: 'someClass', id: 'A' }, { counter: 12 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "A", + className: 'someClass', + id: 'A', }) ).toEqual({ serverData: { counter: 12 }, @@ -81,15 +81,15 @@ describe("SingleInstanceStateController", () => { }); }); - it("can clear all data", () => { + it('can clear all data', () => { SingleInstanceStateController.setServerData( - { className: "someClass", id: "A" }, + { className: 'someClass', id: 'A' }, { counter: 12 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "A", + className: 'someClass', + id: 'A', }) ).toEqual({ serverData: { counter: 12 }, @@ -101,29 +101,25 @@ describe("SingleInstanceStateController", () => { SingleInstanceStateController.clearAllState(); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "A", + className: 'someClass', + id: 'A', }) ).toEqual(null); }); - it("initializes server data when setting pending ops", () => { + it('initializes server data when setting pending ops', () => { expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "B", + className: 'someClass', + id: 'B', }) ).toBe(null); const op = new ParseOps.IncrementOp(1); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "B" }, - "counter", - op - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'B' }, 'counter', op); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "B", + className: 'someClass', + id: 'B', }) ).toEqual({ serverData: {}, @@ -134,15 +130,15 @@ describe("SingleInstanceStateController", () => { }); }); - it("can set server data on an existing state", () => { + it('can set server data on an existing state', () => { SingleInstanceStateController.setServerData( - { className: "someClass", id: "C" }, + { className: 'someClass', id: 'C' }, { counter: 12 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "C", + className: 'someClass', + id: 'C', }) ).toEqual({ serverData: { counter: 12 }, @@ -152,13 +148,13 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.setServerData( - { className: "someClass", id: "C" }, + { className: 'someClass', id: 'C' }, { valid: true } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "C", + className: 'someClass', + id: 'C', }) ).toEqual({ serverData: { counter: 12, valid: true }, @@ -168,13 +164,13 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.setServerData( - { className: "someClass", id: "C" }, + { className: 'someClass', id: 'C' }, { counter: 0 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "C", + className: 'someClass', + id: 'C', }) ).toEqual({ serverData: { counter: 0, valid: true }, @@ -185,15 +181,15 @@ describe("SingleInstanceStateController", () => { }); }); - it("can remove server data from a state", () => { + it('can remove server data from a state', () => { SingleInstanceStateController.setServerData( - { className: "someClass", id: "D" }, + { className: 'someClass', id: 'D' }, { counter: 12 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "D", + className: 'someClass', + id: 'D', }) ).toEqual({ serverData: { counter: 12 }, @@ -203,13 +199,13 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.setServerData( - { className: "someClass", id: "D" }, + { className: 'someClass', id: 'D' }, { counter: undefined } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "D", + className: 'someClass', + id: 'D', }) ).toEqual({ serverData: {}, @@ -220,23 +216,15 @@ describe("SingleInstanceStateController", () => { }); }); - it("can add multiple pending Ops", () => { + it('can add multiple pending Ops', () => { const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "E" }, - "counter", - op - ); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "E" }, - "valid", - op2 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'counter', op); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'valid', op2); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "E", + className: 'someClass', + id: 'E', }) ).toEqual({ serverData: {}, @@ -246,15 +234,11 @@ describe("SingleInstanceStateController", () => { existed: false, }); const op3 = new ParseOps.UnsetOp(); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "E" }, - "valid", - op3 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'valid', op3); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "E", + className: 'someClass', + id: 'E', }) ).toEqual({ serverData: {}, @@ -265,17 +249,13 @@ describe("SingleInstanceStateController", () => { }); }); - it("can unset pending Ops", () => { + it('can unset pending Ops', () => { const op = new ParseOps.IncrementOp(1); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "F" }, - "counter", - op - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'F' }, 'counter', op); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "F", + className: 'someClass', + id: 'F', }) ).toEqual({ serverData: {}, @@ -285,14 +265,14 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "F" }, - "counter", + { className: 'someClass', id: 'F' }, + 'counter', null ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "F", + className: 'someClass', + id: 'F', }) ).toEqual({ serverData: {}, @@ -303,17 +283,13 @@ describe("SingleInstanceStateController", () => { }); }); - it("can push a new pending state frame", () => { + it('can push a new pending state frame', () => { const op = new ParseOps.IncrementOp(1); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "G" }, - "counter", - op - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'G' }, 'counter', op); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "G", + className: 'someClass', + id: 'G', }) ).toEqual({ serverData: {}, @@ -323,13 +299,13 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "G", + className: 'someClass', + id: 'G', }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "G", + className: 'someClass', + id: 'G', }) ).toEqual({ serverData: {}, @@ -339,15 +315,11 @@ describe("SingleInstanceStateController", () => { existed: false, }); const op2 = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "G" }, - "valid", - op2 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'G' }, 'valid', op2); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "G", + className: 'someClass', + id: 'G', }) ).toEqual({ serverData: {}, @@ -358,21 +330,17 @@ describe("SingleInstanceStateController", () => { }); }); - it("can pop a pending state frame", () => { + it('can pop a pending state frame', () => { const op = new ParseOps.IncrementOp(1); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "H" }, - "counter", - op - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'H' }, 'counter', op); SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "H", + className: 'someClass', + id: 'H', }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "H", + className: 'someClass', + id: 'H', }) ).toEqual({ serverData: {}, @@ -383,16 +351,16 @@ describe("SingleInstanceStateController", () => { }); expect( SingleInstanceStateController.popPendingState({ - className: "someClass", - id: "H", + className: 'someClass', + id: 'H', }) ).toEqual({ counter: op, }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "H", + className: 'someClass', + id: 'H', }) ).toEqual({ serverData: {}, @@ -403,15 +371,15 @@ describe("SingleInstanceStateController", () => { }); }); - it("will never leave the pending Op queue empty", () => { + it('will never leave the pending Op queue empty', () => { SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "I", + className: 'someClass', + id: 'I', }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "I", + className: 'someClass', + id: 'I', }) ).toEqual({ serverData: {}, @@ -421,17 +389,17 @@ describe("SingleInstanceStateController", () => { existed: false, }); SingleInstanceStateController.popPendingState({ - className: "someClass", - id: "I", + className: 'someClass', + id: 'I', }); SingleInstanceStateController.popPendingState({ - className: "someClass", - id: "I", + className: 'someClass', + id: 'I', }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "I", + className: 'someClass', + id: 'I', }) ).toEqual({ serverData: {}, @@ -442,120 +410,97 @@ describe("SingleInstanceStateController", () => { }); }); - it("can estimate a single attribute", () => { + it('can estimate a single attribute', () => { expect( - SingleInstanceStateController.estimateAttribute( - { className: "someClass", id: "J" }, - "unset" - ) + SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'unset') ).toBe(undefined); SingleInstanceStateController.setServerData( - { className: "someClass", id: "J" }, + { className: 'someClass', id: 'J' }, { counter: 11 } ); expect( SingleInstanceStateController.estimateAttribute( - { className: "someClass", id: "J" }, - "counter" + { className: 'someClass', id: 'J' }, + 'counter' ) ).toBe(11); const op = new ParseOps.IncrementOp(1); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "J" }, - "counter", - op - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'J' }, 'counter', op); expect( SingleInstanceStateController.estimateAttribute( - { className: "someClass", id: "J" }, - "counter" + { className: 'someClass', id: 'J' }, + 'counter' ) ).toBe(12); SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "J", + className: 'someClass', + id: 'J', }); const op2 = new ParseOps.IncrementOp(10); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "J" }, - "counter", - op2 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'J' }, 'counter', op2); expect( SingleInstanceStateController.estimateAttribute( - { className: "someClass", id: "J" }, - "counter" + { className: 'someClass', id: 'J' }, + 'counter' ) ).toBe(22); }); - it("can estimate all attributes", () => { + it('can estimate all attributes', () => { expect( SingleInstanceStateController.estimateAttributes({ - className: "someClass", - id: "K", + className: 'someClass', + id: 'K', }) ).toEqual({}); SingleInstanceStateController.setServerData( - { className: "someClass", id: "K" }, + { 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 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'counter', op); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'valid', op2); expect( SingleInstanceStateController.estimateAttributes({ - className: "someClass", - id: "K", + className: 'someClass', + id: 'K', }) ).toEqual({ counter: 12, valid: false, }); SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "K", + className: 'someClass', + id: 'K', }); const op3 = new ParseOps.UnsetOp(); - SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "K" }, - "valid", - op3 - ); + SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'valid', op3); expect( SingleInstanceStateController.estimateAttributes({ - className: "someClass", - id: "K", + className: 'someClass', + id: 'K', }) ).toEqual({ counter: 12, }); }); - it("can update server data with changes", () => { + it('can update server data with changes', () => { SingleInstanceStateController.setServerData( - { className: "someClass", id: "L" }, + { className: 'someClass', id: 'L' }, { counter: 11 } ); expect( SingleInstanceStateController.estimateAttributes({ - className: "someClass", - id: "L", + className: 'someClass', + id: 'L', }) ).toEqual({ counter: 11, }); SingleInstanceStateController.commitServerChanges( - { className: "someClass", id: "L" }, + { className: 'someClass', id: 'L' }, { counter: 12, valid: true, @@ -563,8 +508,8 @@ describe("SingleInstanceStateController", () => { ); expect( SingleInstanceStateController.estimateAttributes({ - className: "someClass", - id: "L", + className: 'someClass', + id: 'L', }) ).toEqual({ counter: 12, @@ -572,92 +517,83 @@ describe("SingleInstanceStateController", () => { }); }); - it("can enqueue a chain of tasks", async () => { + it('can enqueue a chain of tasks', async () => { let p1Resolve, p2Resolve; - const p1 = new Promise((resolve) => { + const p1 = new Promise(resolve => { p1Resolve = resolve; }); - const p2 = new Promise((resolve) => { + const p2 = new Promise(resolve => { p2Resolve = resolve; }); const called = [false, false, false]; - SingleInstanceStateController.enqueueTask( - { className: "someClass", id: "M" }, - () => { - return p1.then(() => { - called[0] = true; - }); - } - ); - SingleInstanceStateController.enqueueTask( - { className: "someClass", id: "M" }, - () => { - return p2.then(() => { - called[1] = true; - }); - } - ); - SingleInstanceStateController.enqueueTask( - { className: "someClass", id: "M" }, - () => { - called[2] = true; - return Promise.resolve(); - } - ); + SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { + return p1.then(() => { + called[0] = true; + }); + }); + SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { + return p2.then(() => { + called[1] = true; + }); + }); + SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { + called[2] = true; + return Promise.resolve(); + }); expect(called).toEqual([false, false, false]); p1Resolve(); await p1; expect(called).toEqual([true, false, false]); p2Resolve(); await p2; - await new Promise((resolve) => setImmediate(resolve)); + await new Promise(resolve => setImmediate(resolve)); expect(called).toEqual([true, true, true]); }); - it("can merge the first entry into the next", () => { + it('can merge the first entry into the next', () => { const incCount = new ParseOps.IncrementOp(1); - const setName = new ParseOps.SetOp("demo"); + const setName = new ParseOps.SetOp('demo'); SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "N" }, - "counter", + { className: 'someClass', id: 'N' }, + 'counter', incCount ); SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "N" }, - "name", + { className: 'someClass', id: 'N' }, + 'name', setName ); SingleInstanceStateController.pushPendingState({ - className: "someClass", - id: "N", + className: 'someClass', + id: 'N', }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "N" }, - "counter", + { className: 'someClass', id: 'N' }, + 'counter', setCount ); SingleInstanceStateController.setPendingOp( - { className: "someClass", id: "N" }, - "valid", + { className: 'someClass', id: 'N' }, + 'valid', setValid ); SingleInstanceStateController.mergeFirstPendingState({ - className: "someClass", - id: "N", + className: 'someClass', + id: 'N', }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "N", + className: 'someClass', + id: 'N', }) ).toEqual({ serverData: {}, pendingOps: [ { counter: new ParseOps.SetOp(44), - name: new ParseOps.SetOp("demo"), + name: new ParseOps.SetOp('demo'), valid: new ParseOps.SetOp(true), }, ], @@ -667,54 +603,54 @@ describe("SingleInstanceStateController", () => { }); }); - it("stores cached versions of object attributes", () => { + it('stores cached versions of object attributes', () => { let cache = SingleInstanceStateController.getObjectCache({ - className: "someClass", - id: "O", + className: 'someClass', + id: 'O', }); expect(cache).toEqual({}); SingleInstanceStateController.commitServerChanges( - { className: "someClass", id: "O" }, + { className: 'someClass', id: 'O' }, { - name: "MyObject", + 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", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', }), } ); cache = SingleInstanceStateController.getObjectCache({ - className: "someClass", - id: "O", + 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", + __type: 'GeoPoint', latitude: 20, longitude: 20, }); }); - it("can remove state for an object", () => { + it('can remove state for an object', () => { expect( SingleInstanceStateController.removeState({ - className: "someClass", - id: "P", + className: 'someClass', + id: 'P', }) ).toBe(null); SingleInstanceStateController.setServerData( - { className: "someClass", id: "P" }, + { className: 'someClass', id: 'P' }, { counter: 12 } ); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "P", + className: 'someClass', + id: 'P', }) ).toEqual({ serverData: { counter: 12 }, @@ -724,8 +660,8 @@ describe("SingleInstanceStateController", () => { existed: false, }); const state = SingleInstanceStateController.removeState({ - className: "someClass", - id: "P", + className: 'someClass', + id: 'P', }); expect(state).toEqual({ serverData: { counter: 12 }, @@ -736,27 +672,27 @@ describe("SingleInstanceStateController", () => { }); expect( SingleInstanceStateController.getState({ - className: "someClass", - id: "P", + className: 'someClass', + id: 'P', }) ).toBe(null); }); - it("can duplicate the state of an object", () => { - const obj = { className: "someClass", id: "someId" }; + it('can duplicate the state of an object', () => { + const obj = { className: 'someClass', id: 'someId' }; SingleInstanceStateController.setServerData(obj, { counter: 12, - name: "original", + name: 'original', }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp(obj, "counter", setCount); - SingleInstanceStateController.setPendingOp(obj, "valid", setValid); + SingleInstanceStateController.setPendingOp(obj, 'counter', setCount); + SingleInstanceStateController.setPendingOp(obj, 'valid', setValid); - const duplicate = { className: "someClass", id: "dupId" }; + const duplicate = { className: 'someClass', id: 'dupId' }; SingleInstanceStateController.duplicateState(obj, duplicate); expect(SingleInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: "original" }, + serverData: { counter: 12, name: 'original' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), diff --git a/src/__tests__/Storage-test.js b/src/__tests__/Storage-test.js index 068890787..e3030b088 100644 --- a/src/__tests__/Storage-test.js +++ b/src/__tests__/Storage-test.js @@ -9,9 +9,9 @@ jest.autoMockOff(); -const mockRNStorageInterface = require("./test_helpers/mockRNStorage"); -const mockWeChat = require("./test_helpers/mockWeChat"); -const CoreManager = require("../CoreManager"); +const mockRNStorageInterface = require('./test_helpers/mockRNStorage'); +const mockWeChat = require('./test_helpers/mockWeChat'); +const CoreManager = require('../CoreManager'); global.wx = mockWeChat; @@ -48,262 +48,262 @@ const mockStorageInterface = { global.localStorage = mockStorageInterface; -const BrowserStorageController = require("../StorageController.browser"); +const BrowserStorageController = require('../StorageController.browser'); -describe("Browser StorageController", () => { +describe('Browser StorageController', () => { beforeEach(() => { BrowserStorageController.clear(); }); - it("is synchronous", () => { + it('is synchronous', () => { expect(BrowserStorageController.async).toBe(0); - expect(typeof BrowserStorageController.getItem).toBe("function"); - expect(typeof BrowserStorageController.setItem).toBe("function"); - expect(typeof BrowserStorageController.removeItem).toBe("function"); + expect(typeof BrowserStorageController.getItem).toBe('function'); + expect(typeof BrowserStorageController.setItem).toBe('function'); + expect(typeof BrowserStorageController.removeItem).toBe('function'); }); - it("can store and retrieve values", () => { - expect(BrowserStorageController.getItem("myKey")).toBe(null); - BrowserStorageController.setItem("myKey", "myValue"); - expect(BrowserStorageController.getItem("myKey")).toBe("myValue"); + it('can store and retrieve values', () => { + expect(BrowserStorageController.getItem('myKey')).toBe(null); + BrowserStorageController.setItem('myKey', 'myValue'); + expect(BrowserStorageController.getItem('myKey')).toBe('myValue'); }); - it("can remove values", () => { - BrowserStorageController.setItem("myKey", "myValue"); - expect(BrowserStorageController.getItem("myKey")).toBe("myValue"); - BrowserStorageController.removeItem("myKey"); - expect(BrowserStorageController.getItem("myKey")).toBe(null); + it('can remove values', () => { + BrowserStorageController.setItem('myKey', 'myValue'); + expect(BrowserStorageController.getItem('myKey')).toBe('myValue'); + BrowserStorageController.removeItem('myKey'); + expect(BrowserStorageController.getItem('myKey')).toBe(null); }); }); -const RNStorageController = require("../StorageController.react-native"); +const RNStorageController = require('../StorageController.react-native'); -describe("React Native StorageController", () => { +describe('React Native StorageController', () => { beforeEach(() => { CoreManager.setAsyncStorage(mockRNStorageInterface); RNStorageController.clear(); }); - it("is asynchronous", () => { + it('is asynchronous', () => { expect(RNStorageController.async).toBe(1); - expect(typeof RNStorageController.getItemAsync).toBe("function"); - expect(typeof RNStorageController.setItemAsync).toBe("function"); - expect(typeof RNStorageController.removeItemAsync).toBe("function"); + expect(typeof RNStorageController.getItemAsync).toBe('function'); + expect(typeof RNStorageController.setItemAsync).toBe('function'); + expect(typeof RNStorageController.removeItemAsync).toBe('function'); }); - it("can store and retrieve values", (done) => { - RNStorageController.getItemAsync("myKey") - .then((result) => { + it('can store and retrieve values', done => { + RNStorageController.getItemAsync('myKey') + .then(result => { expect(result).toBe(null); - return RNStorageController.setItemAsync("myKey", "myValue"); + return RNStorageController.setItemAsync('myKey', 'myValue'); }) .then(() => { - return RNStorageController.getItemAsync("myKey"); + return RNStorageController.getItemAsync('myKey'); }) - .then((result) => { - expect(result).toBe("myValue"); + .then(result => { + expect(result).toBe('myValue'); done(); }); }); - it("can remove values", (done) => { - RNStorageController.setItemAsync("myKey", "myValue") + it('can remove values', done => { + RNStorageController.setItemAsync('myKey', 'myValue') .then(() => { - return RNStorageController.getItemAsync("myKey"); + return RNStorageController.getItemAsync('myKey'); }) - .then((result) => { - expect(result).toBe("myValue"); - return RNStorageController.removeItemAsync("myKey"); + .then(result => { + expect(result).toBe('myValue'); + return RNStorageController.removeItemAsync('myKey'); }) .then(() => { - return RNStorageController.getItemAsync("myKey"); + return RNStorageController.getItemAsync('myKey'); }) - .then((result) => { + .then(result => { expect(result).toBe(null); done(); }); }); - it("can getAllKeys", (done) => { - RNStorageController.setItemAsync("myKey", "myValue") + it('can getAllKeys', done => { + RNStorageController.setItemAsync('myKey', 'myValue') .then(() => { - return RNStorageController.getItemAsync("myKey"); + return RNStorageController.getItemAsync('myKey'); }) - .then((result) => { - expect(result).toBe("myValue"); + .then(result => { + expect(result).toBe('myValue'); return RNStorageController.getAllKeysAsync(); }) - .then((keys) => { - expect(keys[0]).toBe("myKey"); + .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); + cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.setItemAsync("myKey", "myValue").catch((error) => { - expect(error).toBe("Error Thrown"); + 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); + cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.getItemAsync("myKey").catch((error) => { - expect(error).toBe("Error Thrown"); + 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); + cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.removeItemAsync("myKey").catch((error) => { - expect(error).toBe("Error Thrown"); + 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); + cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.getAllKeysAsync().catch((error) => { - expect(error).toBe("Error Thrown"); + RNStorageController.getAllKeysAsync().catch(error => { + expect(error).toBe('Error Thrown'); done(); }); }); }); -const DefaultStorageController = require("../StorageController.default"); +const DefaultStorageController = require('../StorageController.default'); -describe("Default StorageController", () => { +describe('Default StorageController', () => { beforeEach(() => { DefaultStorageController.clear(); }); - it("is synchronous", () => { + it('is synchronous', () => { expect(DefaultStorageController.async).toBe(0); - expect(typeof DefaultStorageController.getItem).toBe("function"); - expect(typeof DefaultStorageController.setItem).toBe("function"); - expect(typeof DefaultStorageController.removeItem).toBe("function"); + expect(typeof DefaultStorageController.getItem).toBe('function'); + expect(typeof DefaultStorageController.setItem).toBe('function'); + expect(typeof DefaultStorageController.removeItem).toBe('function'); }); - it("can store and retrieve values", () => { - expect(DefaultStorageController.getItem("myKey")).toBe(null); - DefaultStorageController.setItem("myKey", "myValue"); - expect(DefaultStorageController.getItem("myKey")).toBe("myValue"); + it('can store and retrieve values', () => { + expect(DefaultStorageController.getItem('myKey')).toBe(null); + DefaultStorageController.setItem('myKey', 'myValue'); + expect(DefaultStorageController.getItem('myKey')).toBe('myValue'); }); - it("can remove values", () => { - DefaultStorageController.setItem("myKey", "myValue"); - expect(DefaultStorageController.getItem("myKey")).toBe("myValue"); - DefaultStorageController.removeItem("myKey"); - expect(DefaultStorageController.getItem("myKey")).toBe(null); + it('can remove values', () => { + DefaultStorageController.setItem('myKey', 'myValue'); + expect(DefaultStorageController.getItem('myKey')).toBe('myValue'); + DefaultStorageController.removeItem('myKey'); + expect(DefaultStorageController.getItem('myKey')).toBe(null); }); }); -const WeappStorageController = require("../StorageController.weapp"); +const WeappStorageController = require('../StorageController.weapp'); -describe("WeChat StorageController", () => { +describe('WeChat StorageController', () => { beforeEach(() => { WeappStorageController.clear(); }); - it("is synchronous", () => { + it('is synchronous', () => { expect(WeappStorageController.async).toBe(0); - expect(typeof WeappStorageController.getItem).toBe("function"); - expect(typeof WeappStorageController.setItem).toBe("function"); - expect(typeof WeappStorageController.removeItem).toBe("function"); + expect(typeof WeappStorageController.getItem).toBe('function'); + expect(typeof WeappStorageController.setItem).toBe('function'); + expect(typeof WeappStorageController.removeItem).toBe('function'); }); - it("can store and retrieve values", () => { - expect(WeappStorageController.getItem("myKey")).toBe(undefined); - WeappStorageController.setItem("myKey", "myValue"); - expect(WeappStorageController.getItem("myKey")).toBe("myValue"); - expect(WeappStorageController.getAllKeys()).toEqual(["myKey"]); + it('can store and retrieve values', () => { + expect(WeappStorageController.getItem('myKey')).toBe(undefined); + WeappStorageController.setItem('myKey', 'myValue'); + expect(WeappStorageController.getItem('myKey')).toBe('myValue'); + expect(WeappStorageController.getAllKeys()).toEqual(['myKey']); }); - it("can remove values", () => { - WeappStorageController.setItem("myKey", "myValue"); - expect(WeappStorageController.getItem("myKey")).toBe("myValue"); - WeappStorageController.removeItem("myKey"); - expect(WeappStorageController.getItem("myKey")).toBe(undefined); + it('can remove values', () => { + WeappStorageController.setItem('myKey', 'myValue'); + expect(WeappStorageController.getItem('myKey')).toBe('myValue'); + WeappStorageController.removeItem('myKey'); + expect(WeappStorageController.getItem('myKey')).toBe(undefined); }); }); -const Storage = require("../Storage"); +const Storage = require('../Storage'); -describe("Storage (Default StorageController)", () => { +describe('Storage (Default StorageController)', () => { beforeEach(() => { - CoreManager.setStorageController(require("../StorageController.default")); + CoreManager.setStorageController(require('../StorageController.default')); }); - it("can store and retrieve values", () => { - expect(Storage.getItem("myKey")).toBe(null); - Storage.setItem("myKey", "myValue"); - expect(Storage.getItem("myKey")).toBe("myValue"); - expect(Storage.getAllKeys()).toEqual(["myKey"]); + it('can store and retrieve values', () => { + expect(Storage.getItem('myKey')).toBe(null); + Storage.setItem('myKey', 'myValue'); + expect(Storage.getItem('myKey')).toBe('myValue'); + expect(Storage.getAllKeys()).toEqual(['myKey']); }); - it("can remove values", () => { - Storage.setItem("myKey", "myValue"); - expect(Storage.getItem("myKey")).toBe("myValue"); - Storage.removeItem("myKey"); - expect(Storage.getItem("myKey")).toBe(null); + it('can remove values', () => { + Storage.setItem('myKey', 'myValue'); + expect(Storage.getItem('myKey')).toBe('myValue'); + Storage.removeItem('myKey'); + expect(Storage.getItem('myKey')).toBe(null); }); - it("wraps synchronous methods in async wrappers", (done) => { - Storage.getItemAsync("myKey") - .then((result) => { + it('wraps synchronous methods in async wrappers', done => { + Storage.getItemAsync('myKey') + .then(result => { expect(result).toBe(null); - return Storage.setItemAsync("myKey", "myValue"); + return Storage.setItemAsync('myKey', 'myValue'); }) .then(() => { - return Storage.getItemAsync("myKey"); + return Storage.getItemAsync('myKey'); }) - .then((result) => { - expect(result).toBe("myValue"); - return Storage.removeItemAsync("myKey"); + .then(result => { + expect(result).toBe('myValue'); + return Storage.removeItemAsync('myKey'); }) .then(() => { - return Storage.getItemAsync("myKey"); + return Storage.getItemAsync('myKey'); }) .then(() => { done(); }); }); - it("can generate a unique storage path", () => { - expect(Storage.generatePath.bind(null, "hello")).toThrow( - "You need to call Parse.initialize before using Parse." + it('can generate a unique storage path', () => { + expect(Storage.generatePath.bind(null, 'hello')).toThrow( + 'You need to call Parse.initialize before using Parse.' ); - CoreManager.set("APPLICATION_ID", "appid"); + CoreManager.set('APPLICATION_ID', 'appid'); expect(Storage.generatePath.bind(null, 12)).toThrow( - "Tried to get a Storage path that was not a String." + 'Tried to get a Storage path that was not a String.' ); - expect(Storage.generatePath("hello")).toBe("Parse/appid/hello"); - expect(Storage.generatePath("/hello")).toBe("Parse/appid/hello"); + expect(Storage.generatePath('hello')).toBe('Parse/appid/hello'); + expect(Storage.generatePath('/hello')).toBe('Parse/appid/hello'); }); - it("can clear if controller does not implement clear", () => { + it('can clear if controller does not implement clear', () => { CoreManager.setStorageController({ getItem: () => {}, setItem: () => {}, @@ -314,48 +314,46 @@ describe("Storage (Default StorageController)", () => { }); }); -describe("Storage (Async 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", () => { + it('throws when using a synchronous method', () => { expect(Storage.getItem).toThrow( - "Synchronous storage is not supported by the current storage controller" + 'Synchronous storage is not supported by the current storage controller' ); expect(Storage.setItem).toThrow( - "Synchronous storage is not supported by the current storage controller" + 'Synchronous storage is not supported by the current storage controller' ); expect(Storage.removeItem).toThrow( - "Synchronous storage is not supported by the current storage controller" + 'Synchronous storage is not supported by the current storage controller' ); expect(Storage.getAllKeys).toThrow( - "Synchronous storage is not supported by the current storage controller" + 'Synchronous storage is not supported by the current storage controller' ); }); - it("wraps synchronous methods in async wrappers", (done) => { - Storage.getItemAsync("myKey") - .then((result) => { + it('wraps synchronous methods in async wrappers', done => { + Storage.getItemAsync('myKey') + .then(result => { expect(result).toBe(null); - return Storage.setItemAsync("myKey", "myValue"); + return Storage.setItemAsync('myKey', 'myValue'); }) .then(() => { - return Storage.getItemAsync("myKey"); + return Storage.getItemAsync('myKey'); }) - .then((result) => { - expect(result).toBe("myValue"); + .then(result => { + expect(result).toBe('myValue'); return Storage.getAllKeysAsync(); }) - .then((result) => { - expect(result).toEqual(["myKey"]); - return Storage.removeItemAsync("myKey"); + .then(result => { + expect(result).toEqual(['myKey']); + return Storage.removeItemAsync('myKey'); }) .then(() => { - return Storage.getItemAsync("myKey"); + return Storage.getItemAsync('myKey'); }) .then(() => { done(); diff --git a/src/__tests__/TaskQueue-test.js b/src/__tests__/TaskQueue-test.js index ca21ca30d..8de725b16 100644 --- a/src/__tests__/TaskQueue-test.js +++ b/src/__tests__/TaskQueue-test.js @@ -9,19 +9,19 @@ jest.autoMockOff(); -const TaskQueue = require("../TaskQueue"); -const { resolvingPromise } = require("../promiseUtils"); +const TaskQueue = require('../TaskQueue'); +const { resolvingPromise } = require('../promiseUtils'); -describe("TaskQueue", () => { - it("is initialized with an empty queue", () => { +describe('TaskQueue', () => { + it('is initialized with an empty queue', () => { const q = new TaskQueue(); expect(q.queue).toEqual([]); }); - it("runs a single task immediately", async () => { + 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,11 +33,11 @@ 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)); @@ -47,24 +47,20 @@ describe("TaskQueue", () => { return p; }); expect(called).toBe(true); - reject("error"); + reject('error'); try { await t; - done.fail("should throw"); + done.fail('should throw'); } catch (e) { done(); } }); - it("can execute a chain of tasks", async () => { + it('can execute a chain of tasks', async () => { const q = new TaskQueue(); const called = [false, false, false]; const completed = [false, false, false]; - const promises = [ - resolvingPromise(), - resolvingPromise(), - resolvingPromise(), - ]; + const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; q.enqueue(() => { called[0] = true; return promises[0].then(() => { @@ -86,29 +82,25 @@ describe("TaskQueue", () => { expect(called).toEqual([true, false, false]); expect(completed).toEqual([false, false, false]); promises[0].resolve(); - await new Promise((r) => setImmediate(r)); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(completed).toEqual([true, false, false]); expect(q.queue.length).toBe(2); promises[1].resolve(); - await new Promise((r) => setImmediate(r)); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(completed).toEqual([true, true, false]); expect(q.queue.length).toBe(1); promises[2].resolve(); - await new Promise((r) => setImmediate(r)); + await new Promise(r => setImmediate(r)); expect(completed).toEqual([true, true, true]); expect(q.queue.length).toBe(0); }); - it("continues the chain when a task errors", async () => { + it('continues the chain when a task errors', async () => { const q = new TaskQueue(); const called = [false, false, false]; - const promises = [ - resolvingPromise(), - resolvingPromise(), - resolvingPromise(), - ]; + const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; q.enqueue(() => { called[0] = true; return promises[0]; @@ -123,27 +115,23 @@ describe("TaskQueue", () => { }); expect(called).toEqual([true, false, false]); promises[0].catch(() => {}); - promises[0].reject("oops"); - await new Promise((r) => setImmediate(r)); + promises[0].reject('oops'); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(q.queue.length).toBe(2); promises[1].resolve(); - await new Promise((r) => setImmediate(r)); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(q.queue.length).toBe(1); promises[2].resolve(); - await new Promise((r) => setImmediate(r)); + await new Promise(r => setImmediate(r)); expect(q.queue.length).toBe(0); }); - it("continues the chain when all tasks errors", async () => { + it('continues the chain when all tasks errors', async () => { const q = new TaskQueue(); const called = [false, false, false]; - const promises = [ - resolvingPromise(), - resolvingPromise(), - resolvingPromise(), - ]; + const promises = [resolvingPromise(), resolvingPromise(), resolvingPromise()]; q.enqueue(() => { called[0] = true; return promises[0]; @@ -162,20 +150,20 @@ describe("TaskQueue", () => { expect(called).toEqual([true, false, false]); promises[0].catch(() => {}); - promises[0].reject("1 oops"); - await new Promise((r) => setImmediate(r)); + promises[0].reject('1 oops'); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, false]); expect(q.queue.length).toBe(2); promises[1].catch(() => {}); - promises[1].reject("2 oops"); - await new Promise((r) => setImmediate(r)); + promises[1].reject('2 oops'); + await new Promise(r => setImmediate(r)); expect(called).toEqual([true, true, true]); expect(q.queue.length).toBe(1); promises[2].catch(() => {}); - promises[2].reject("3 oops"); - await new Promise((r) => setImmediate(r)); + promises[2].reject('3 oops'); + await new Promise(r => setImmediate(r)); expect(q.queue.length).toBe(0); }); }); diff --git a/src/__tests__/UniqueInstanceStateController-test.js b/src/__tests__/UniqueInstanceStateController-test.js index 0790a2cc7..3b056ad3e 100644 --- a/src/__tests__/UniqueInstanceStateController-test.js +++ b/src/__tests__/UniqueInstanceStateController-test.js @@ -7,48 +7,48 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ObjectStateMutations"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParseOp"); -jest.dontMock("../UniqueInstanceStateController"); -jest.dontMock("../TaskQueue"); -jest.dontMock("../promiseUtils"); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ObjectStateMutations'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParseOp'); +jest.dontMock('../UniqueInstanceStateController'); +jest.dontMock('../TaskQueue'); +jest.dontMock('../promiseUtils'); jest.useFakeTimers(); const mockObject = function (className) { this.className = className; }; mockObject.registerSubclass = function () {}; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParseObject = require("../ParseObject"); -const ParseOps = require("../ParseOp"); -const UniqueInstanceStateController = require("../UniqueInstanceStateController"); -const TaskQueue = require("../TaskQueue"); -const { resolvingPromise } = require("../promiseUtils"); +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseObject = require('../ParseObject'); +const ParseOps = require('../ParseOp'); +const UniqueInstanceStateController = require('../UniqueInstanceStateController'); +const TaskQueue = require('../TaskQueue'); +const { resolvingPromise } = require('../promiseUtils'); -describe("UniqueInstanceStateController", () => { - it("returns null state for an unknown object", () => { +describe('UniqueInstanceStateController', () => { + it('returns null state for an unknown object', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); }); - it("returns empty data for an unknown object", () => { + it('returns empty data for an unknown object', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getServerData(obj)).toEqual({}); }); - it("returns an empty op queue for an unknown object", () => { + it('returns an empty op queue for an unknown object', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getPendingOps(obj)).toEqual([{}]); }); - it("initializes server data when setting state", () => { + it('initializes server data when setting state', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); @@ -61,7 +61,7 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can clear all data", () => { + it('can clear all data', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -75,11 +75,11 @@ describe("UniqueInstanceStateController", () => { expect(UniqueInstanceStateController.getState(obj)).toEqual(null); }); - it("initializes server data when setting pending ops", () => { + it('initializes server data when setting pending ops', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.getState(obj)).toBe(null); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], @@ -89,7 +89,7 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can set server data on an existing state", () => { + it('can set server data on an existing state', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -117,7 +117,7 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can remove server data from a state", () => { + it('can remove server data from a state', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -137,12 +137,12 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can add multiple pending Ops", () => { + it('can add multiple pending Ops', () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); - UniqueInstanceStateController.setPendingOp(obj, "valid", op2); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op2 }], @@ -151,7 +151,7 @@ describe("UniqueInstanceStateController", () => { existed: false, }); const op3 = new ParseOps.UnsetOp(); - UniqueInstanceStateController.setPendingOp(obj, "valid", op3); + UniqueInstanceStateController.setPendingOp(obj, 'valid', op3); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op3 }], @@ -161,10 +161,10 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can unset pending Ops", () => { + it('can unset pending Ops', () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], @@ -172,7 +172,7 @@ describe("UniqueInstanceStateController", () => { tasks: new TaskQueue(), existed: false, }); - UniqueInstanceStateController.setPendingOp(obj, "counter", null); + UniqueInstanceStateController.setPendingOp(obj, 'counter', null); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{}], @@ -182,10 +182,10 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can push a new pending state frame", () => { + it('can push a new pending state frame', () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }], @@ -202,7 +202,7 @@ describe("UniqueInstanceStateController", () => { existed: false, }); const op2 = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, "valid", op2); + UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{ counter: op }, { valid: op2 }], @@ -212,10 +212,10 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can pop a pending state frame", () => { + it('can pop a pending state frame', () => { const obj = new ParseObject(); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, @@ -236,7 +236,7 @@ describe("UniqueInstanceStateController", () => { }); }); - it("will never leave the pending Op queue empty", () => { + it('will never leave the pending Op queue empty', () => { const obj = new ParseObject(); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -257,49 +257,41 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can estimate a single attribute", () => { + 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); + expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(11); const op = new ParseOps.IncrementOp(1); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); - expect( - UniqueInstanceStateController.estimateAttribute(obj, "counter") - ).toBe(12); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(12); UniqueInstanceStateController.pushPendingState(obj); const op2 = new ParseOps.IncrementOp(10); - UniqueInstanceStateController.setPendingOp(obj, "counter", op2); - expect( - UniqueInstanceStateController.estimateAttribute(obj, "counter") - ).toBe(22); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op2); + expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(22); }); - it("can estimate all attributes", () => { + it('can estimate all attributes', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({}); UniqueInstanceStateController.setServerData(obj, { counter: 11 }); const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(false); - UniqueInstanceStateController.setPendingOp(obj, "counter", op); - UniqueInstanceStateController.setPendingOp(obj, "valid", op2); + UniqueInstanceStateController.setPendingOp(obj, 'counter', op); + UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ counter: 12, valid: false, }); UniqueInstanceStateController.pushPendingState(obj); const op3 = new ParseOps.UnsetOp(); - UniqueInstanceStateController.setPendingOp(obj, "valid", op3); + UniqueInstanceStateController.setPendingOp(obj, 'valid', op3); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ counter: 12, }); }); - it("can update server data with changes", () => { + it('can update server data with changes', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 11 }); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ @@ -315,7 +307,7 @@ describe("UniqueInstanceStateController", () => { }); }); - it("can enqueue a chain of tasks", async () => { + it('can enqueue a chain of tasks', async () => { const obj = new ParseObject(); const p1 = resolvingPromise(); const p2 = resolvingPromise(); @@ -346,24 +338,24 @@ describe("UniqueInstanceStateController", () => { expect(called).toEqual([true, true, true]); }); - it("can merge the first entry into the next", () => { + it('can merge the first entry into the next', () => { const obj = new ParseObject(); const incCount = new ParseOps.IncrementOp(1); - const setName = new ParseOps.SetOp("demo"); - UniqueInstanceStateController.setPendingOp(obj, "counter", incCount); - UniqueInstanceStateController.setPendingOp(obj, "name", setName); + const setName = new ParseOps.SetOp('demo'); + UniqueInstanceStateController.setPendingOp(obj, 'counter', incCount); + UniqueInstanceStateController.setPendingOp(obj, 'name', setName); UniqueInstanceStateController.pushPendingState(obj); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, "counter", setCount); - UniqueInstanceStateController.setPendingOp(obj, "valid", setValid); + UniqueInstanceStateController.setPendingOp(obj, 'counter', setCount); + UniqueInstanceStateController.setPendingOp(obj, 'valid', setValid); UniqueInstanceStateController.mergeFirstPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [ { counter: new ParseOps.SetOp(44), - name: new ParseOps.SetOp("demo"), + name: new ParseOps.SetOp('demo'), valid: new ParseOps.SetOp(true), }, ], @@ -373,18 +365,18 @@ describe("UniqueInstanceStateController", () => { }); }); - it("stores cached versions of object attributes", () => { + it('stores cached versions of object attributes', () => { const obj = new ParseObject(); let cache = UniqueInstanceStateController.getObjectCache(obj); expect(cache).toEqual({}); UniqueInstanceStateController.commitServerChanges(obj, { - name: "MyObject", + 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", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', }), }); cache = UniqueInstanceStateController.getObjectCache(obj); @@ -392,13 +384,13 @@ describe("UniqueInstanceStateController", () => { expect(cache.file).toBe(undefined); expect(JSON.parse(cache.obj)).toEqual({ a: 12, b: 21 }); expect(JSON.parse(cache.location)).toEqual({ - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 20, longitude: 20, }); }); - it("can remove state for an object", () => { + it('can remove state for an object', () => { const obj = new ParseObject(); expect(UniqueInstanceStateController.removeState(obj)).toBe(null); UniqueInstanceStateController.setServerData(obj, { counter: 12 }); @@ -420,7 +412,7 @@ describe("UniqueInstanceStateController", () => { expect(UniqueInstanceStateController.getState(obj)).toBe(null); }); - it("can allocate many objects without running out of memory", () => { + it('can allocate many objects without running out of memory', () => { const closure = function () { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { spacious: true }); @@ -430,21 +422,21 @@ describe("UniqueInstanceStateController", () => { } }); - it("can duplicate the state of an object", () => { + it('can duplicate the state of an object', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 12, - name: "original", + name: 'original', }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - UniqueInstanceStateController.setPendingOp(obj, "counter", setCount); - UniqueInstanceStateController.setPendingOp(obj, "valid", setValid); + UniqueInstanceStateController.setPendingOp(obj, 'counter', setCount); + UniqueInstanceStateController.setPendingOp(obj, 'valid', setValid); const duplicate = new ParseObject(); UniqueInstanceStateController.duplicateState(obj, duplicate); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: "original" }, + serverData: { counter: 12, name: 'original' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), @@ -452,17 +444,17 @@ describe("UniqueInstanceStateController", () => { }); UniqueInstanceStateController.setServerData(duplicate, { - name: "duplicate", + name: 'duplicate', }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ - serverData: { counter: 12, name: "original" }, + serverData: { counter: 12, name: 'original' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), existed: false, }); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: "duplicate" }, + serverData: { counter: 12, name: 'duplicate' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), @@ -471,14 +463,14 @@ describe("UniqueInstanceStateController", () => { UniqueInstanceStateController.commitServerChanges(obj, { o: { a: 12 } }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ - serverData: { counter: 12, name: "original", o: { a: 12 } }, + serverData: { counter: 12, name: 'original', o: { a: 12 } }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: { o: '{"a":12}' }, tasks: new TaskQueue(), existed: false, }); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ - serverData: { counter: 12, name: "duplicate" }, + serverData: { counter: 12, name: 'duplicate' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), @@ -488,7 +480,7 @@ describe("UniqueInstanceStateController", () => { const otherDup = new ParseObject(); UniqueInstanceStateController.duplicateState(obj, otherDup); expect(UniqueInstanceStateController.getState(otherDup)).toEqual({ - serverData: { counter: 12, name: "original", o: { a: 12 } }, + serverData: { counter: 12, name: 'original', o: { a: 12 } }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: { o: '{"a":12}' }, tasks: new TaskQueue(), diff --git a/src/__tests__/arrayContainsObject-test.js b/src/__tests__/arrayContainsObject-test.js index f51140763..d53f9ff18 100644 --- a/src/__tests__/arrayContainsObject-test.js +++ b/src/__tests__/arrayContainsObject-test.js @@ -7,37 +7,35 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../arrayContainsObject"); +jest.dontMock('../arrayContainsObject'); let localCount = 0; const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { - this._localId = "local" + localCount++; + this._localId = 'local' + localCount++; } }; mockObject.prototype._getId = function () { return this.id || this._localId; }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const arrayContainsObject = require("../arrayContainsObject").default; -const ParseObject = require("../ParseObject"); +const arrayContainsObject = require('../arrayContainsObject').default; +const ParseObject = require('../ParseObject'); -describe("arrayContainsObject", () => { - it("detects objects by their id", () => { - const o = new ParseObject("Item"); +describe('arrayContainsObject', () => { + it('detects objects by their id', () => { + const o = new ParseObject('Item'); expect(arrayContainsObject([], o)).toBe(false); - expect(arrayContainsObject([1, "string"], 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')], new ParseObject('Item'))).toBe(false); expect( arrayContainsObject( - [new ParseObject("Item", "a"), new ParseObject("Item", "b")], - new ParseObject("Item", "a") + [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 b51056223..3b77c4d83 100644 --- a/src/__tests__/browser-test.js +++ b/src/__tests__/browser-test.js @@ -1,15 +1,15 @@ -jest.dontMock("../CoreManager"); -jest.dontMock("../CryptoController"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../ParseError"); -jest.dontMock("../EventEmitter"); -jest.dontMock("../Parse"); -jest.dontMock("../RESTController"); -jest.dontMock("../Storage"); -jest.dontMock("crypto-js/aes"); +jest.dontMock('../CoreManager'); +jest.dontMock('../CryptoController'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../ParseError'); +jest.dontMock('../EventEmitter'); +jest.dontMock('../Parse'); +jest.dontMock('../RESTController'); +jest.dontMock('../Storage'); +jest.dontMock('crypto-js/aes'); -const ParseError = require("../ParseError").default; +const ParseError = require('../ParseError').default; class XMLHttpRequest {} class XDomainRequest { @@ -19,46 +19,46 @@ class XDomainRequest { global.XMLHttpRequest = XMLHttpRequest; global.XDomainRequest = XDomainRequest; -describe("Browser", () => { +describe('Browser', () => { beforeEach(() => { - process.env.PARSE_BUILD = "browser"; + process.env.PARSE_BUILD = 'browser'; jest.clearAllMocks(); }); afterEach(() => { - process.env.PARSE_BUILD = "node"; + process.env.PARSE_BUILD = 'node'; }); - it("warning initializing parse/node in browser", () => { - const Parse = require("../Parse"); - jest.spyOn(console, "log").mockImplementationOnce(() => {}); - jest.spyOn(Parse, "_initialize").mockImplementationOnce(() => {}); - Parse.initialize("A", "B"); + it('warning initializing parse/node in browser', () => { + const Parse = require('../Parse'); + 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(Parse._initialize).toHaveBeenCalledTimes(1); }); - it("initializing parse/node in browser with server rendering", () => { + it('initializing parse/node in browser with server rendering', () => { process.env.SERVER_RENDERING = true; - const Parse = require("../Parse"); - jest.spyOn(console, "log").mockImplementationOnce(() => {}); - jest.spyOn(Parse, "_initialize").mockImplementationOnce(() => {}); - Parse.initialize("A", "B"); + const Parse = require('../Parse'); + jest.spyOn(console, 'log').mockImplementationOnce(() => {}); + jest.spyOn(Parse, '_initialize').mockImplementationOnce(() => {}); + Parse.initialize('A', 'B'); expect(console.log).toHaveBeenCalledTimes(0); expect(Parse._initialize).toHaveBeenCalledTimes(1); }); - it("load StorageController", () => { - const StorageController = require("../StorageController.browser"); - jest.spyOn(StorageController, "setItem"); - const storage = require("../Storage"); - storage.setItem("key", "value"); + it('load StorageController', () => { + const StorageController = require('../StorageController.browser'); + jest.spyOn(StorageController, 'setItem'); + const storage = require('../Storage'); + storage.setItem('key', 'value'); expect(StorageController.setItem).toHaveBeenCalledTimes(1); }); - it("load RESTController with IE9", async () => { + it('load RESTController with IE9', async () => { let called = false; class XDomainRequest { open() { @@ -71,15 +71,15 @@ describe("Browser", () => { } } global.XDomainRequest = XDomainRequest; - console.log("hererer"); - const RESTController = require("../RESTController"); + console.log('hererer'); + const RESTController = require('../RESTController'); const options = { progress: () => {}, requestTask: () => {}, }; const { response } = await RESTController.ajax( - "POST", - "classes/TestObject", + 'POST', + 'classes/TestObject', null, null, options @@ -88,23 +88,23 @@ describe("Browser", () => { expect(called).toBe(true); }); - it("RESTController IE9 Ajax timeout error", async () => { + it('RESTController IE9 Ajax timeout error', async () => { let called = false; class XDomainRequest { open() { called = true; } send() { - this.responseText = ""; + this.responseText = ''; this.ontimeout(); } } class XMLHttpRequest {} global.XDomainRequest = XDomainRequest; global.XMLHttpRequest = XMLHttpRequest; - const RESTController = require("../RESTController"); + const RESTController = require('../RESTController'); try { - await RESTController.ajax("POST", "classes/TestObject"); + await RESTController.ajax('POST', 'classes/TestObject'); expect(true).toBe(false); } catch (e) { const errorResponse = JSON.stringify({ @@ -116,26 +116,26 @@ describe("Browser", () => { expect(called).toBe(true); }); - it("RESTController IE9 Ajax response error", async () => { + it('RESTController IE9 Ajax response error', async () => { let called = false; class XDomainRequest { open() { called = true; } send() { - this.responseText = ""; + this.responseText = ''; this.onload(); } } class XMLHttpRequest {} global.XDomainRequest = XDomainRequest; global.XMLHttpRequest = XMLHttpRequest; - const RESTController = require("../RESTController"); + const RESTController = require('../RESTController'); try { - await RESTController.ajax("POST", "classes/TestObject"); + await RESTController.ajax('POST', 'classes/TestObject'); expect(true).toBe(false); } catch (e) { - expect(e.message).toBe("Unexpected end of JSON input"); + expect(e.message).toBe('Unexpected end of JSON input'); } expect(called).toBe(true); }); diff --git a/src/__tests__/canBeSerialized-test.js b/src/__tests__/canBeSerialized-test.js index ab06c34eb..f9a99d9d3 100644 --- a/src/__tests__/canBeSerialized-test.js +++ b/src/__tests__/canBeSerialized-test.js @@ -7,14 +7,14 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../canBeSerialized"); +jest.dontMock('../canBeSerialized'); function mockObject(id, attributes) { this.id = id; this.attributes = attributes; } mockObject.registerSubclass = function () {}; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); function mockFile(url) { this._url = url; @@ -22,55 +22,55 @@ function mockFile(url) { mockFile.prototype.url = function () { return this._url; }; -jest.setMock("../ParseFile", mockFile); +jest.setMock('../ParseFile', mockFile); -const canBeSerialized = require("../canBeSerialized").default; -const ParseFile = require("../ParseFile"); -const ParseObject = require("../ParseObject"); -const ParseRelation = require("../ParseRelation").default; +const canBeSerialized = require('../canBeSerialized').default; +const ParseFile = require('../ParseFile'); +const ParseObject = require('../ParseObject'); +const ParseRelation = require('../ParseRelation').default; -describe("canBeSerialized", () => { - it("returns true for anything that is not a ParseObject", () => { +describe('canBeSerialized', () => { + it('returns true for anything that is not a ParseObject', () => { expect(canBeSerialized(12)).toBe(true); - expect(canBeSerialized("string")).toBe(true); + expect(canBeSerialized('string')).toBe(true); expect(canBeSerialized(false)).toBe(true); expect(canBeSerialized([])).toBe(true); expect(canBeSerialized({})).toBe(true); }); - it("validates primitives", () => { - const o = new ParseObject("oid", { + it('validates primitives', () => { + const o = new ParseObject('oid', { a: 12, - b: "string", + b: 'string', c: false, }); expect(canBeSerialized(o)).toBe(true); }); - it("returns false when a child is an unsaved object or file", () => { - let o = new ParseObject("oid", { + it('returns false when a child is an unsaved object or file', () => { + let o = new ParseObject('oid', { a: new ParseObject(), }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject("oid", { - a: new ParseObject("oid2", {}), + o = new ParseObject('oid', { + a: new ParseObject('oid2', {}), }); expect(canBeSerialized(o)).toBe(true); - o = new ParseObject("oid", { + o = new ParseObject('oid', { a: new ParseFile(), }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject("oid", { - a: new ParseFile("http://files.parsetfss.com/a/parse.txt"), + o = new ParseObject('oid', { + a: new ParseFile('http://files.parsetfss.com/a/parse.txt'), }); expect(canBeSerialized(o)).toBe(true); }); - it("returns true when all children have an id", () => { - const child = new ParseObject("child", {}); + it('returns true when all children have an id', () => { + const child = new ParseObject('child', {}); const parent = new ParseObject(undefined, { child: child, }); @@ -79,7 +79,7 @@ describe("canBeSerialized", () => { expect(canBeSerialized(child)).toBe(false); }); - it("returns true for relations", () => { + it('returns true for relations', () => { const relation = new ParseRelation(null, null); const parent = new ParseObject(undefined, { child: relation, @@ -87,8 +87,8 @@ describe("canBeSerialized", () => { expect(canBeSerialized(parent)).toBe(true); }); - it("traverses nested arrays and objects", () => { - let o = new ParseObject("oid", { + it('traverses nested arrays and objects', () => { + let o = new ParseObject('oid', { a: { a: { a: { @@ -99,18 +99,18 @@ describe("canBeSerialized", () => { }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject("oid", { + o = new ParseObject('oid', { a: { a: { a: { - b: new ParseObject("oid2"), + b: new ParseObject('oid2'), }, }, }, }); expect(canBeSerialized(o)).toBe(true); - o = new ParseObject("oid", { + o = new ParseObject('oid', { a: [ 1, 2, @@ -122,13 +122,13 @@ describe("canBeSerialized", () => { }); expect(canBeSerialized(o)).toBe(false); - o = new ParseObject("oid", { + o = new ParseObject('oid', { a: [ 1, 2, 3, { - b: new ParseObject("oid2"), + b: new ParseObject('oid2'), }, ], }); diff --git a/src/__tests__/decode-test.js b/src/__tests__/decode-test.js index 4daf3c01a..47b5cc5c2 100644 --- a/src/__tests__/decode-test.js +++ b/src/__tests__/decode-test.js @@ -7,39 +7,39 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../decode"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); -jest.dontMock("../ParsePolygon"); +jest.dontMock('../decode'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); +jest.dontMock('../ParsePolygon'); -const decode = require("../decode").default; +const decode = require('../decode').default; -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParseObject = require("../ParseObject").default; -const ParsePolygon = require("../ParsePolygon").default; +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseObject = require('../ParseObject').default; +const ParsePolygon = require('../ParsePolygon').default; -describe("decode", () => { - it("ignores primitives", () => { +describe('decode', () => { + it('ignores primitives', () => { expect(decode(undefined)).toBe(undefined); expect(decode(null)).toBe(null); expect(decode(true)).toBe(true); expect(decode(12)).toBe(12); - expect(decode("string")).toBe("string"); + expect(decode('string')).toBe('string'); }); - it("decodes dates", () => { + it('decodes dates', () => { expect( decode({ - __type: "Date", - iso: "2015-02-01T00:00:00.000Z", + __type: 'Date', + iso: '2015-02-01T00:00:00.000Z', }) ).toEqual(new Date(Date.UTC(2015, 1))); }); - it("decodes GeoPoints", () => { + it('decodes GeoPoints', () => { const point = decode({ - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 40.5, longitude: 50.4, }); @@ -48,7 +48,7 @@ describe("decode", () => { expect(point.longitude).toBe(50.4); }); - it("decodes Polygons", () => { + it('decodes Polygons', () => { const points = [ [0, 0], [0, 1], @@ -57,68 +57,66 @@ describe("decode", () => { [0, 0], ]; const polygon = decode({ - __type: "Polygon", + __type: 'Polygon', coordinates: points, }); expect(polygon instanceof ParsePolygon).toBe(true); expect(polygon.coordinates).toEqual(points); }); - it("decodes Files", () => { + it('decodes Files', () => { const file = decode({ - __type: "File", - name: "parse.txt", - url: "https://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'https://files.parsetfss.com/a/parse.txt', }); expect(file instanceof ParseFile).toBe(true); - expect(file.name()).toBe("parse.txt"); - expect(file.url()).toBe("https://files.parsetfss.com/a/parse.txt"); + expect(file.name()).toBe('parse.txt'); + expect(file.url()).toBe('https://files.parsetfss.com/a/parse.txt'); }); - it("decodes Relations", () => { + it('decodes Relations', () => { const obj = decode({ - __type: "Relation", - className: "Delivery", + __type: 'Relation', + className: 'Delivery', }); expect(obj.constructor.mock.calls[0]).toEqual([null, null]); - expect(obj.targetClassName).toBe("Delivery"); + expect(obj.targetClassName).toBe('Delivery'); }); - it("decodes Pointers", () => { + it('decodes Pointers', () => { const data = { - __type: "Pointer", - className: "Item", - objectId: "1001", + __type: 'Pointer', + className: 'Item', + objectId: '1001', }; decode(data); expect(ParseObject.fromJSON.mock.calls[0][0]).toEqual(data); }); - it("decodes ParseObjects", () => { + it('decodes ParseObjects', () => { const data = { - __type: "Object", - className: "Item", - objectId: "1001", + __type: 'Object', + className: 'Item', + 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([new Date(Date.UTC(2015, 1)), 12, "string"]); + it('iterates over arrays', () => { + expect(decode([{ __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, 12, 'string'])).toEqual([ + new Date(Date.UTC(2015, 1)), + 12, + 'string', + ]); }); - it("iterates over objects", () => { + it('iterates over objects', () => { expect( decode({ empty: null, - when: { __type: "Date", iso: "2015-04-01T00:00:00.000Z" }, + when: { __type: 'Date', iso: '2015-04-01T00:00:00.000Z' }, count: 15, }) ).toEqual({ diff --git a/src/__tests__/encode-test.js b/src/__tests__/encode-test.js index 8d42d1173..8b5e1a1b6 100644 --- a/src/__tests__/encode-test.js +++ b/src/__tests__/encode-test.js @@ -7,10 +7,10 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../encode"); -jest.dontMock("../ParseACL"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseGeoPoint"); +jest.dontMock('../encode'); +jest.dontMock('../ParseACL'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseGeoPoint'); const mockObject = function (className) { this.className = className; @@ -21,13 +21,13 @@ mockObject.prototype = { return this._serverData; }, toPointer() { - return "POINTER"; + return 'POINTER'; }, toOfflinePointer() { - return "OFFLINE_POINTER"; + return 'OFFLINE_POINTER'; }, _getId() { - return "local1234"; + return 'local1234'; }, dirty() {}, toJSON() { @@ -35,81 +35,75 @@ mockObject.prototype = { }, _toFullJSON(seen, offline) { const json = { - __type: "Object", + __type: 'Object', className: this.className, }; for (const attr in this.attributes) { - json[attr] = encode( - this.attributes[attr], - false, - false, - seen.concat(this), - offline - ); + json[attr] = encode(this.attributes[attr], false, false, seen.concat(this), offline); } return json; }, }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const encode = require("../encode").default; -const ParseACL = require("../ParseACL").default; -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParseObject = require("../ParseObject"); -const ParseRelation = require("../ParseRelation").default; +const encode = require('../encode').default; +const ParseACL = require('../ParseACL').default; +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseObject = require('../ParseObject'); +const ParseRelation = require('../ParseRelation').default; -describe("encode", () => { - it("ignores primitives", () => { +describe('encode', () => { + it('ignores primitives', () => { expect(encode(undefined)).toBe(undefined); expect(encode(null)).toBe(null); expect(encode(true)).toBe(true); expect(encode(12)).toBe(12); - expect(encode("string")).toBe("string"); + expect(encode('string')).toBe('string'); }); - it("encodes dates", () => { + it('encodes dates', () => { expect(encode(new Date(Date.UTC(2015, 1)))).toEqual({ - __type: "Date", - iso: "2015-02-01T00:00:00.000Z", + __type: 'Date', + iso: '2015-02-01T00:00:00.000Z', }); expect(encode.bind(null, new Date(Date.parse(null)))).toThrow( - "Tried to encode an invalid date." + 'Tried to encode an invalid date.' ); }); - it("encodes regular expressions", () => { - expect(encode(new RegExp("^hello"))).toEqual("^hello"); - expect(encode(/a[^b]+c/g)).toEqual("a[^b]+c"); + it('encodes regular expressions', () => { + expect(encode(new RegExp('^hello'))).toEqual('^hello'); + expect(encode(/a[^b]+c/g)).toEqual('a[^b]+c'); }); - it("encodes GeoPoints", () => { + it('encodes GeoPoints', () => { const point = new ParseGeoPoint(40.5, 50.4); expect(encode(point)).toEqual({ - __type: "GeoPoint", + __type: 'GeoPoint', latitude: 40.5, longitude: 50.4, }); }); - it("encodes Files", () => { - const file = new ParseFile("parse.txt"); - expect(encode.bind(null, file)).toThrow("Tried to encode an unsaved file."); - file._url = "https://files.parsetfss.com/a/parse.txt"; + it('encodes Files', () => { + const file = new ParseFile('parse.txt'); + expect(encode.bind(null, file)).toThrow('Tried to encode an unsaved file.'); + file._url = 'https://files.parsetfss.com/a/parse.txt'; expect(encode(file)).toEqual({ - __type: "File", - name: "parse.txt", - url: "https://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: 'parse.txt', + url: 'https://files.parsetfss.com/a/parse.txt', }); }); - it("encodes Relations", () => { + it('encodes Relations', () => { const rel = new ParseRelation(); encode(rel); expect(rel.toJSON.mock.calls.length).toBe(1); }); - it("encodes ACLs", () => { + it('encodes ACLs', () => { const acl = new ParseACL({ aUserId: { read: true, write: false } }); expect(encode(acl)).toEqual({ aUserId: { @@ -119,93 +113,83 @@ describe("encode", () => { }); }); - it("encodes ParseObjects", () => { - const obj = new ParseObject("Item"); + it('encodes ParseObjects', () => { + const obj = new ParseObject('Item'); obj._serverData = {}; - expect(encode(obj)).toEqual("POINTER"); + expect(encode(obj)).toEqual('POINTER'); obj._serverData = obj.attributes = { - str: "string", + str: 'string', date: new Date(Date.UTC(2015, 1, 1)), }; expect(encode(obj)).toEqual({ - __type: "Object", - className: "Item", - str: "string", + __type: 'Object', + className: 'Item', + str: 'string', date: { - __type: "Date", - iso: "2015-02-01T00:00:00.000Z", + __type: 'Date', + iso: '2015-02-01T00:00:00.000Z', }, }); obj.attributes.self = obj; expect(encode(obj)).toEqual({ - __type: "Object", - className: "Item", - str: "string", + __type: 'Object', + className: 'Item', + str: 'string', date: { - __type: "Date", - iso: "2015-02-01T00:00:00.000Z", + __type: 'Date', + iso: '2015-02-01T00:00:00.000Z', }, - self: "POINTER", + self: 'POINTER', }); }); - it("encodes ParseObjects offline", () => { - const obj = new ParseObject("Item"); + it('encodes ParseObjects offline', () => { + const obj = new ParseObject('Item'); obj._serverData = {}; - expect(encode(obj, false, false, undefined, true)).toEqual( - "OFFLINE_POINTER" - ); + expect(encode(obj, false, false, undefined, true)).toEqual('OFFLINE_POINTER'); obj._serverData = obj.attributes = { - str: "string", + str: 'string', date: new Date(Date.UTC(2015, 1, 1)), }; obj.attributes.self = obj; expect(encode(obj, false, false, undefined, true)).toEqual({ - __type: "Object", - className: "Item", - str: "string", + __type: 'Object', + className: 'Item', + str: 'string', date: { - __type: "Date", - iso: "2015-02-01T00:00:00.000Z", + __type: 'Date', + 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" - ); + 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'); }); - 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", - ]); + 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']); 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", () => { + 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", + date: { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, + str: 'abc', }); }); }); diff --git a/src/__tests__/equals-test.js b/src/__tests__/equals-test.js index 50a8b1503..e4331f2af 100644 --- a/src/__tests__/equals-test.js +++ b/src/__tests__/equals-test.js @@ -9,15 +9,15 @@ jest.autoMockOff(); -const equals = require("../equals").default; -const ParseACL = require("../ParseACL").default; -const ParseFile = require("../ParseFile").default; -const ParseGeoPoint = require("../ParseGeoPoint").default; -const ParseObject = require("../ParseObject").default; - -describe("equals", () => { - it("tests equality of primitives", () => { - expect(equals(1, "string")).toBe(false); +const equals = require('../equals').default; +const ParseACL = require('../ParseACL').default; +const ParseFile = require('../ParseFile').default; +const ParseGeoPoint = require('../ParseGeoPoint').default; +const ParseObject = require('../ParseObject').default; + +describe('equals', () => { + it('tests equality of primitives', () => { + expect(equals(1, 'string')).toBe(false); expect(equals(1, true)).toBe(false); expect(equals(1, undefined)).toBe(false); expect(equals(1, null)).toBe(false); @@ -25,13 +25,13 @@ describe("equals", () => { expect(equals(1, 4)).toBe(false); expect(equals(1, 1)).toBe(true); - expect(equals(null, "string")).toBe(false); - expect(equals(true, "string")).toBe(false); - expect(equals(undefined, "string")).toBe(false); - expect(equals(true, "string")).toBe(false); - expect(equals({}, "string")).toBe(false); - expect(equals("abc", "def")).toBe(false); - expect(equals("abc", "abc")).toBe(true); + expect(equals(null, 'string')).toBe(false); + expect(equals(true, 'string')).toBe(false); + expect(equals(undefined, 'string')).toBe(false); + expect(equals(true, 'string')).toBe(false); + expect(equals({}, 'string')).toBe(false); + expect(equals('abc', 'def')).toBe(false); + expect(equals('abc', 'abc')).toBe(true); expect(equals(false, false)).toBe(true); expect(equals(true, true)).toBe(true); @@ -42,7 +42,7 @@ describe("equals", () => { expect(equals(null, undefined)).toBe(false); }); - it("tests equality of objects and arrays", () => { + it('tests equality of objects and arrays', () => { const a = {}; expect(equals(a, a)).toBe(true); expect(equals({}, {})).toBe(true); @@ -60,7 +60,7 @@ describe("equals", () => { expect(equals([{ c: 3 }, 2, 1], [{ c: 3 }, 2, 1])).toBe(true); }); - it("tests equality of ACLs", () => { + it('tests equality of ACLs', () => { // Defer to ParseACL tests for the majority of testing const a = new ParseACL(); const b = new ParseACL(); @@ -75,7 +75,7 @@ describe("equals", () => { expect(equals(b, a)).toBe(false); }); - it("tests equality of GeoPoints", () => { + it('tests equality of GeoPoints', () => { // Defer to ParseGeoPoint tests for the majority of testing const a = new ParseGeoPoint(40, 40); expect(equals(a, a)).toBe(true); @@ -89,62 +89,62 @@ describe("equals", () => { expect(equals(b, a)).toBe(false); }); - it("tests equality of Files", () => { + it('tests equality of Files', () => { // Defer to ParseFile tests for the majority of testing - let a = new ParseFile("parse.txt", [61, 170, 236, 120]); - let b = new ParseFile("parse.txt", [61, 170, 236, 120]); + let a = new ParseFile('parse.txt', [61, 170, 236, 120]); + let b = new ParseFile('parse.txt', [61, 170, 236, 120]); expect(equals(a, a)).toBe(true); // unsaved files are never equal expect(equals(a, b)).toBe(false); a = ParseFile.fromJSON({ - __type: "File", - name: "parse.txt", - url: "http://files.parsetfss.com/a/parse.txt", + __type: 'File', + name: '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", + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', }); expect(equals(a, b)).toBe(true); }); - it("tests equality of ParseObjects", () => { + it('tests equality of ParseObjects', () => { // Defer to ParseObject tests for the majority of testing - const a = new ParseObject("Item"); - const b = new ParseObject("Item"); + const a = new ParseObject('Item'); + const b = new ParseObject('Item'); expect(equals(a, a)).toBe(true); expect(equals(a, b)).toBe(false); - a.id = "myobj"; - b.id = "myobj"; + a.id = 'myobj'; + b.id = 'myobj'; expect(equals(a, b)).toBe(true); const c = { - __type: "Pointer", - className: "Item", - objectId: "myobj", + __type: 'Pointer', + className: 'Item', + objectId: 'myobj', }; const d = { - __type: "Object", - className: "Item", - objectId: "myobj", + __type: 'Object', + className: 'Item', + objectId: 'myobj', }; const e = { - __type: "Unknown", - className: "Item", - objectId: "myobj", + __type: 'Unknown', + className: 'Item', + objectId: 'myobj', }; expect(equals(c, b)).toBe(true); expect(equals(d, b)).toBe(true); expect(equals(e, b)).toBe(false); }); - it("tests equality of Date", () => { - const a = new Date("2018-08-09T00:01:53.964Z"); - const b = new Date("2018-08-10T00:00:00.000Z"); + it('tests equality of Date', () => { + const a = new Date('2018-08-09T00:01:53.964Z'); + const b = new Date('2018-08-10T00:00:00.000Z'); expect(equals(a, a)).toBe(true); expect(equals(a, b)).toBe(false); diff --git a/src/__tests__/escape-test.js b/src/__tests__/escape-test.js index 14a28d248..be063f6a1 100644 --- a/src/__tests__/escape-test.js +++ b/src/__tests__/escape-test.js @@ -9,20 +9,18 @@ jest.autoMockOff(); -const escape = require("../escape.js").default; +const escape = require('../escape.js').default; -describe("escape", () => { - it("escapes special HTML characters", () => { - expect(escape("&")).toBe("&"); - expect(escape("<")).toBe("<"); - expect(escape(">")).toBe(">"); - expect(escape("'")).toBe("'"); - expect(escape('"')).toBe("""); - expect(escape("/")).toBe("/"); +describe('escape', () => { + it('escapes special HTML characters', () => { + 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 2ed195c1b..476a12af9 100644 --- a/src/__tests__/parseDate-test.js +++ b/src/__tests__/parseDate-test.js @@ -9,19 +9,19 @@ jest.autoMockOff(); -const parseDate = require("../parseDate").default; +const parseDate = require('../parseDate').default; -describe("parseDate", () => { - it("returns a Date for valid strings", () => { - expect(Number(parseDate("2013-12-14T04:51:19.582Z"))).toBe( +describe('parseDate', () => { + it('returns a Date for valid strings', () => { + expect(Number(parseDate('2013-12-14T04:51:19.582Z'))).toBe( Number(new Date(Date.UTC(2013, 11, 14, 4, 51, 19, 582))) ); - expect(Number(parseDate("2013-12-14T04:51:19Z"))).toBe( + expect(Number(parseDate('2013-12-14T04:51:19Z'))).toBe( Number(new Date(Date.UTC(2013, 11, 14, 4, 51, 19))) ); }); - it("returns null for invalid strings", () => { - expect(parseDate("asdf")).toBe(null); + it('returns null for invalid strings', () => { + expect(parseDate('asdf')).toBe(null); }); }); diff --git a/src/__tests__/promiseUtils-test.js b/src/__tests__/promiseUtils-test.js index c7d1180d2..41ff17ded 100644 --- a/src/__tests__/promiseUtils-test.js +++ b/src/__tests__/promiseUtils-test.js @@ -1,9 +1,9 @@ jest.autoMockOff(); -const { when } = require("../promiseUtils"); +const { when } = require('../promiseUtils'); -describe("promiseUtils", () => { - it("when", async () => { +describe('promiseUtils', () => { + it('when', async () => { const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); @@ -13,7 +13,7 @@ describe("promiseUtils", () => { result = await when(promise1, promise2); expect(result).toEqual([1, 2]); - result = await when(promise1, "not a promise"); - expect(result).toEqual([1, "not a promise"]); + result = await when(promise1, 'not a promise'); + expect(result).toEqual([1, 'not a promise']); }); }); diff --git a/src/__tests__/react-native-test.js b/src/__tests__/react-native-test.js index aac312480..3d7b4cc62 100644 --- a/src/__tests__/react-native-test.js +++ b/src/__tests__/react-native-test.js @@ -1,77 +1,77 @@ /* global WebSocket */ -jest.dontMock("../CoreManager"); -jest.dontMock("../CryptoController"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../EventEmitter"); -jest.dontMock("../LiveQueryClient"); -jest.dontMock("../LocalDatastore"); -jest.dontMock("../ParseObject"); -jest.dontMock("../Storage"); +jest.dontMock('../CoreManager'); +jest.dontMock('../CryptoController'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../EventEmitter'); +jest.dontMock('../LiveQueryClient'); +jest.dontMock('../LocalDatastore'); +jest.dontMock('../ParseObject'); +jest.dontMock('../Storage'); jest.mock( - "../../../../react-native/Libraries/vendor/emitter/EventEmitter", + '../../../../react-native/Libraries/vendor/emitter/EventEmitter', () => { return { prototype: { - addListener: new (require("events").EventEmitter)(), + addListener: new (require('events').EventEmitter)(), }, }; }, { virtual: true } ); -const mockEmitter = require("../../../../react-native/Libraries/vendor/emitter/EventEmitter"); -const CoreManager = require("../CoreManager"); +const mockEmitter = require('../../../../react-native/Libraries/vendor/emitter/EventEmitter'); +const CoreManager = require('../CoreManager'); -describe("React Native", () => { +describe('React Native', () => { beforeEach(() => { - process.env.PARSE_BUILD = "react-native"; + process.env.PARSE_BUILD = 'react-native'; }); afterEach(() => { - process.env.PARSE_BUILD = "node"; + process.env.PARSE_BUILD = 'node'; }); - it("load EventEmitter", () => { - const eventEmitter = require("../EventEmitter"); + it('load EventEmitter', () => { + const eventEmitter = require('../EventEmitter'); expect(eventEmitter).toEqual(mockEmitter); }); - it("load CryptoController", () => { - const CryptoJS = require("react-native-crypto-js"); - jest.spyOn(CryptoJS.AES, "encrypt").mockImplementation(() => { + it('load CryptoController', () => { + const CryptoJS = require('react-native-crypto-js'); + jest.spyOn(CryptoJS.AES, 'encrypt').mockImplementation(() => { return { - toString: () => "World", + toString: () => 'World', }; }); - const CryptoController = require("../CryptoController"); - const phrase = CryptoController.encrypt({}, "salt"); - expect(phrase).toBe("World"); + const CryptoController = require('../CryptoController'); + const phrase = CryptoController.encrypt({}, 'salt'); + expect(phrase).toBe('World'); expect(CryptoJS.AES.encrypt).toHaveBeenCalled(); }); - it("load LocalDatastoreController", () => { - const LocalDatastoreController = require("../LocalDatastoreController.react-native"); - require("../LocalDatastore"); + it('load LocalDatastoreController', () => { + const LocalDatastoreController = require('../LocalDatastoreController.react-native'); + require('../LocalDatastore'); const LDC = CoreManager.getLocalDatastoreController(); expect(LocalDatastoreController).toEqual(LDC); }); - it("load StorageController", () => { - const StorageController = require("../StorageController.react-native"); - jest.spyOn(StorageController, "setItemAsync"); - const storage = require("../Storage"); - storage.setItemAsync("key", "value"); + it('load StorageController', () => { + const StorageController = require('../StorageController.react-native'); + jest.spyOn(StorageController, 'setItemAsync'); + const storage = require('../Storage'); + storage.setItemAsync('key', 'value'); expect(StorageController.setItemAsync).toHaveBeenCalledTimes(1); }); - it("load WebSocketController", () => { - jest.mock("../EventEmitter", () => { - return require("events").EventEmitter; + it('load WebSocketController', () => { + jest.mock('../EventEmitter', () => { + return require('events').EventEmitter; }); const socket = WebSocket; - require("../LiveQueryClient"); + require('../LiveQueryClient'); const websocket = CoreManager.getWebSocketController(); expect(websocket).toEqual(socket); }); diff --git a/src/__tests__/unique-test.js b/src/__tests__/unique-test.js index 306ee99ff..bc30f339f 100644 --- a/src/__tests__/unique-test.js +++ b/src/__tests__/unique-test.js @@ -7,55 +7,53 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../arrayContainsObject"); -jest.dontMock("../unique"); +jest.dontMock('../arrayContainsObject'); +jest.dontMock('../unique'); let localCount = 0; const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { - this._localId = "local" + localCount++; + this._localId = 'local' + localCount++; } }; mockObject.prototype._getId = function () { return this.id || this._localId; }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const unique = require("../unique").default; -const ParseObject = require("../ParseObject"); +const unique = require('../unique').default; +const ParseObject = require('../ParseObject'); -describe("unique", () => { - it("produces an array with unique elements", () => { +describe('unique', () => { + it('produces an array with unique elements', () => { expect(unique([])).toEqual([]); expect(unique([1])).toEqual([1]); expect(unique([3, 4, 1])).toEqual([3, 4, 1]); expect(unique([3, 4, 3, 1])).toEqual([3, 4, 1]); expect(unique([2, 2, 2, 2, 2, 2, 2])).toEqual([2]); - expect(unique(["a", "b", "c", "a", "d"])).toEqual(["a", "b", "c", "d"]); + expect(unique(['a', 'b', 'c', 'a', 'd'])).toEqual(['a', 'b', 'c', 'd']); }); - it("dedups objects by their id", () => { - const o = new ParseObject("Item"); + 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'), new ParseObject('Item')]).length).toBe(2); expect( unique([ - new ParseObject("Item", "a"), - new ParseObject("Item", "b"), - new ParseObject("Item", "a"), + new ParseObject('Item', 'a'), + new ParseObject('Item', 'b'), + new ParseObject('Item', 'a'), ]) - ).toEqual([new ParseObject("Item", "a"), new ParseObject("Item", "b")]); + ).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"), + 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")]); + ).toEqual([new ParseObject('Item', 'a'), new ParseObject('Item', 'b')]); }); }); diff --git a/src/__tests__/unsavedChildren-test.js b/src/__tests__/unsavedChildren-test.js index 2e79c93e7..d4eea094f 100644 --- a/src/__tests__/unsavedChildren-test.js +++ b/src/__tests__/unsavedChildren-test.js @@ -7,8 +7,8 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -jest.dontMock("../ParseFile"); -jest.dontMock("../unsavedChildren"); +jest.dontMock('../ParseFile'); +jest.dontMock('../unsavedChildren'); function mockObject({ className, localId, id, attributes, dirty }) { this.className = className; @@ -26,24 +26,24 @@ mockObject.prototype = { return this._dirty; }, }; -jest.setMock("../ParseObject", mockObject); +jest.setMock('../ParseObject', mockObject); -const ParseFile = require("../ParseFile").default; -const ParseObject = require("../ParseObject"); -const ParseRelation = require("../ParseRelation").default; -const unsavedChildren = require("../unsavedChildren").default; +const ParseFile = require('../ParseFile').default; +const ParseObject = require('../ParseObject'); +const ParseRelation = require('../ParseRelation').default; +const unsavedChildren = require('../unsavedChildren').default; -describe("unsavedChildren", () => { - it("finds unsaved files", () => { +describe('unsavedChildren', () => { + it('finds unsaved files', () => { 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('parse1.txt', [61, 170, 236, 120]), + new ParseFile('parse2.txt', [61, 170, 236, 120]), + new ParseFile('parse3.txt', [61, 170, 236, 120]), ]; const f = new ParseObject({ - className: "Folder", - id: "121", + className: 'Folder', + id: '121', attributes: { a: files[0], b: files[1], @@ -67,11 +67,11 @@ describe("unsavedChildren", () => { expect(unsavedChildren(f)).toEqual([files[0], files[1], files[2]]); }); - it("only returns unique files", () => { - const file = new ParseFile("parse1.txt", [61, 170, 236, 120]); + it('only returns unique files', () => { + const file = new ParseFile('parse1.txt', [61, 170, 236, 120]); const f = new ParseObject({ - className: "Folder", - id: "121", + className: 'Folder', + id: '121', attributes: { a: file, b: file, @@ -81,22 +81,22 @@ describe("unsavedChildren", () => { expect(unsavedChildren(f)).toEqual([file]); }); - it("finds unsaved child objects", () => { + it('finds unsaved child objects', () => { const a = new ParseObject({ - className: "File", - localId: "local0", + className: 'File', + localId: 'local0', attributes: {}, dirty: true, }); const b = new ParseObject({ - className: "File", - localId: "local1", + className: 'File', + localId: 'local1', attributes: {}, dirty: true, }); const f = new ParseObject({ - className: "Folder", - id: "121", + className: 'Folder', + id: '121', attributes: { a: a, b: b, @@ -121,50 +121,48 @@ describe("unsavedChildren", () => { expect(unsavedChildren(f)).toEqual([a, b]); }); - it("throws on nested objects without ids", () => { + it('throws on nested objects without ids', () => { const a = new ParseObject({ - className: "File", - localId: "local0", + className: 'File', + localId: 'local0', attributes: {}, dirty: true, }); const b = new ParseObject({ - className: "File", - localId: "local1", + className: 'File', + localId: 'local1', attributes: { a: a, }, dirty: true, }); const f = new ParseObject({ - className: "Folder", - id: "121", + className: 'Folder', + id: '121', attributes: { 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", () => { + it('can explicitly allow nested objects without ids', () => { const a = new ParseObject({ - className: "Folder", - localId: "local0", + className: 'Folder', + localId: 'local0', dirty: true, attributes: {}, }); const b = new ParseObject({ - className: "Folder", - localId: "local1", + className: 'Folder', + localId: 'local1', dirty: true, attributes: {}, }); const c = new ParseObject({ - className: "File", - localId: "local2", + className: 'File', + localId: 'local2', dirty: true, attributes: {}, }); @@ -175,14 +173,14 @@ describe("unsavedChildren", () => { expect(unsavedChildren(a, true)).toEqual([b, c]); }); - it("does not revisit objects", () => { + it('does not revisit objects', () => { const a = new ParseObject({ - className: "File", - id: "130", + className: 'File', + id: '130', attributes: { b: new ParseObject({ - className: "File", - localId: "131", + className: 'File', + localId: '131', attributes: {}, dirty: true, }), @@ -194,11 +192,11 @@ describe("unsavedChildren", () => { expect(unsavedChildren(a)).toEqual([a.attributes.b]); }); - it("skips Relation", () => { + it('skips Relation', () => { const relation = new ParseRelation(null, null); const f = new ParseObject({ - className: "Folder", - id: "121", + className: 'Folder', + id: '121', attributes: { r: relation, }, diff --git a/src/__tests__/weapp-test.js b/src/__tests__/weapp-test.js index 1fa3339b0..01293e08b 100644 --- a/src/__tests__/weapp-test.js +++ b/src/__tests__/weapp-test.js @@ -1,65 +1,65 @@ -jest.dontMock("../CoreManager"); -jest.dontMock("../CryptoController"); -jest.dontMock("../decode"); -jest.dontMock("../encode"); -jest.dontMock("../EventEmitter"); -jest.dontMock("../LiveQueryClient"); -jest.dontMock("../Parse"); -jest.dontMock("../ParseFile"); -jest.dontMock("../ParseObject"); -jest.dontMock("../RESTController"); -jest.dontMock("../Socket.weapp"); -jest.dontMock("../Storage"); -jest.dontMock("crypto-js/aes"); -jest.dontMock("./test_helpers/mockWeChat"); +jest.dontMock('../CoreManager'); +jest.dontMock('../CryptoController'); +jest.dontMock('../decode'); +jest.dontMock('../encode'); +jest.dontMock('../EventEmitter'); +jest.dontMock('../LiveQueryClient'); +jest.dontMock('../Parse'); +jest.dontMock('../ParseFile'); +jest.dontMock('../ParseObject'); +jest.dontMock('../RESTController'); +jest.dontMock('../Socket.weapp'); +jest.dontMock('../Storage'); +jest.dontMock('crypto-js/aes'); +jest.dontMock('./test_helpers/mockWeChat'); -const CoreManager = require("../CoreManager"); -const mockWeChat = require("./test_helpers/mockWeChat"); +const CoreManager = require('../CoreManager'); +const mockWeChat = require('./test_helpers/mockWeChat'); global.wx = mockWeChat; -describe("WeChat", () => { +describe('WeChat', () => { beforeEach(() => { - process.env.PARSE_BUILD = "weapp"; + process.env.PARSE_BUILD = 'weapp'; }); afterEach(() => { - process.env.PARSE_BUILD = "node"; + process.env.PARSE_BUILD = 'node'; }); - it("load StorageController", () => { - const StorageController = require("../StorageController.weapp"); - jest.spyOn(StorageController, "setItem"); - const storage = require("../Storage"); - storage.setItem("key", "value"); + it('load StorageController', () => { + const StorageController = require('../StorageController.weapp'); + jest.spyOn(StorageController, 'setItem'); + const storage = require('../Storage'); + storage.setItem('key', 'value'); expect(StorageController.setItem).toHaveBeenCalledTimes(1); }); - it("load RESTController", () => { - const XHR = require("../Xhr.weapp"); - const RESTController = require("../RESTController"); + it('load RESTController', () => { + const XHR = require('../Xhr.weapp'); + const RESTController = require('../RESTController'); expect(RESTController._getXHR()).toEqual(XHR); }); - it("load ParseFile", () => { - const XHR = require("../Xhr.weapp"); - require("../ParseFile"); + it('load ParseFile', () => { + const XHR = require('../Xhr.weapp'); + require('../ParseFile'); const fileController = CoreManager.getFileController(); expect(fileController._getXHR()).toEqual(XHR); }); - it("load WebSocketController", () => { - const socket = require("../Socket.weapp"); - require("../LiveQueryClient"); + it('load WebSocketController', () => { + const socket = require('../Socket.weapp'); + require('../LiveQueryClient'); const websocket = CoreManager.getWebSocketController(); expect(websocket).toEqual(socket); }); - describe("Socket", () => { - it("send", () => { - const Websocket = require("../Socket.weapp"); - jest.spyOn(mockWeChat, "connectSocket"); - const socket = new Websocket("wss://examples.com"); + describe('Socket', () => { + it('send', () => { + const Websocket = require('../Socket.weapp'); + jest.spyOn(mockWeChat, 'connectSocket'); + const socket = new Websocket('wss://examples.com'); socket.onopen(); socket.onmessage(); socket.onclose(); @@ -71,7 +71,7 @@ describe("WeChat", () => { expect(mockWeChat.connectSocket).toHaveBeenCalled(); - socket.send("{}"); + socket.send('{}'); expect(socket.onopen).toHaveBeenCalled(); expect(socket.onmessage).toHaveBeenCalled(); diff --git a/src/arrayContainsObject.js b/src/arrayContainsObject.js index 752b92a6d..17f1d927c 100644 --- a/src/arrayContainsObject.js +++ b/src/arrayContainsObject.js @@ -9,12 +9,9 @@ * @flow */ -import ParseObject from "./ParseObject"; +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; } diff --git a/src/canBeSerialized.js b/src/canBeSerialized.js index 3145d95b0..417a1f1fe 100644 --- a/src/canBeSerialized.js +++ b/src/canBeSerialized.js @@ -9,9 +9,9 @@ * @flow */ -import ParseFile from "./ParseFile"; -import ParseObject from "./ParseObject"; -import ParseRelation from "./ParseRelation"; +import ParseFile from './ParseFile'; +import ParseObject from './ParseObject'; +import ParseRelation from './ParseRelation'; export default function canBeSerialized(obj: ParseObject): boolean { if (!(obj instanceof ParseObject)) { @@ -28,7 +28,7 @@ export default function canBeSerialized(obj: ParseObject): boolean { } function canBeSerializedHelper(value: any): boolean { - if (typeof value !== "object") { + if (typeof value !== 'object') { return true; } if (value instanceof ParseRelation) { diff --git a/src/decode.js b/src/decode.js index 41cf6f213..ac4cca011 100644 --- a/src/decode.js +++ b/src/decode.js @@ -8,16 +8,16 @@ * * @flow */ -import ParseACL from "./ParseACL"; // eslint-disable-line no-unused-vars -import ParseFile from "./ParseFile"; -import ParseGeoPoint from "./ParseGeoPoint"; -import ParsePolygon from "./ParsePolygon"; -import ParseObject from "./ParseObject"; -import { opFromJSON } from "./ParseOp"; -import ParseRelation from "./ParseRelation"; +import ParseACL from './ParseACL'; // eslint-disable-line no-unused-vars +import ParseFile from './ParseFile'; +import ParseGeoPoint from './ParseGeoPoint'; +import ParsePolygon from './ParsePolygon'; +import ParseObject from './ParseObject'; +import { opFromJSON } from './ParseOp'; +import ParseRelation from './ParseRelation'; export default function decode(value: any): any { - if (value === null || typeof value !== "object") { + if (value === null || typeof value !== 'object') { return value; } if (Array.isArray(value)) { @@ -27,34 +27,34 @@ export default function decode(value: any): any { }); return dup; } - if (typeof value.__op === "string") { + if (typeof value.__op === 'string') { return opFromJSON(value); } - if (value.__type === "Pointer" && value.className) { + if (value.__type === 'Pointer' && value.className) { return ParseObject.fromJSON(value); } - if (value.__type === "Object" && value.className) { + if (value.__type === 'Object' && value.className) { return ParseObject.fromJSON(value); } - if (value.__type === "Relation") { + if (value.__type === 'Relation') { // The parent and key fields will be populated by the parent const relation = new ParseRelation(null, null); relation.targetClassName = value.className; return relation; } - if (value.__type === "Date") { + if (value.__type === 'Date') { return new Date(value.iso); } - if (value.__type === "File") { + if (value.__type === 'File') { return ParseFile.fromJSON(value); } - if (value.__type === "GeoPoint") { + if (value.__type === 'GeoPoint') { return new ParseGeoPoint({ latitude: value.latitude, longitude: value.longitude, }); } - if (value.__type === "Polygon") { + if (value.__type === 'Polygon') { return new ParsePolygon(value.coordinates); } const copy = {}; diff --git a/src/encode.js b/src/encode.js index 1b000d2b1..a7800af1f 100644 --- a/src/encode.js +++ b/src/encode.js @@ -9,13 +9,13 @@ * @flow */ -import ParseACL from "./ParseACL"; -import ParseFile from "./ParseFile"; -import ParseGeoPoint from "./ParseGeoPoint"; -import ParsePolygon from "./ParsePolygon"; -import ParseObject from "./ParseObject"; -import { Op } from "./ParseOp"; -import ParseRelation from "./ParseRelation"; +import ParseACL from './ParseACL'; +import ParseFile from './ParseFile'; +import ParseGeoPoint from './ParseGeoPoint'; +import ParsePolygon from './ParsePolygon'; +import ParseObject from './ParseObject'; +import { Op } from './ParseOp'; +import ParseRelation from './ParseRelation'; function encode( value: mixed, @@ -26,9 +26,9 @@ function encode( ): any { if (value instanceof ParseObject) { if (disallowObjects) { - throw new Error("Parse Objects not allowed here"); + throw new Error('Parse Objects not allowed here'); } - const seenEntry = value.id ? value.className + ":" + value.id : value; + const seenEntry = value.id ? value.className + ':' + value.id : value; if ( forcePointers || !seen || @@ -36,7 +36,7 @@ function encode( value.dirty() || Object.keys(value._getServerData()).length < 1 ) { - if (offline && value._getId().startsWith("local")) { + if (offline && value._getId().startsWith('local')) { return value.toOfflinePointer(); } return value.toPointer(); @@ -55,39 +55,33 @@ function encode( } if (value instanceof ParseFile) { if (!value.url()) { - throw new Error("Tried to encode an unsaved file."); + throw new Error('Tried to encode an unsaved file.'); } return value.toJSON(); } - if (Object.prototype.toString.call(value) === "[object Date]") { + if (Object.prototype.toString.call(value) === '[object Date]') { if (isNaN(value)) { - throw new Error("Tried to encode an invalid date."); + throw new Error('Tried to encode an invalid date.'); } - return { __type: "Date", iso: (value: any).toJSON() }; + return { __type: 'Date', iso: (value: any).toJSON() }; } if ( - Object.prototype.toString.call(value) === "[object RegExp]" && - typeof value.source === "string" + 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); }); } - if (value && typeof value === "object") { + if (value && typeof value === 'object') { const output = {}; for (const k in value) { - output[k] = encode( - value[k], - disallowObjects, - forcePointers, - seen, - offline - ); + output[k] = encode(value[k], disallowObjects, forcePointers, seen, offline); } return output; } diff --git a/src/equals.js b/src/equals.js index 807bc159a..8080f9c39 100644 --- a/src/equals.js +++ b/src/equals.js @@ -7,17 +7,14 @@ * of patent rights can be found in the PATENTS file in the same directory. */ -import ParseACL from "./ParseACL"; -import ParseFile from "./ParseFile"; -import ParseGeoPoint from "./ParseGeoPoint"; -import ParseObject from "./ParseObject"; +import ParseACL from './ParseACL'; +import ParseFile from './ParseFile'; +import ParseGeoPoint from './ParseGeoPoint'; +import ParseObject from './ParseObject'; export default function equals(a, b) { const toString = Object.prototype.toString; - if ( - toString.call(a) === "[object Date]" || - toString.call(b) === "[object Date]" - ) { + if (toString.call(a) === '[object Date]' || toString.call(b) === '[object Date]') { const dateA = new Date(a); const dateB = new Date(b); return +dateA === +dateB; @@ -27,7 +24,7 @@ export default function equals(a, b) { return false; } - if (!a || typeof a !== "object") { + if (!a || typeof a !== 'object') { // a is a primitive return a === b; } @@ -56,7 +53,7 @@ export default function equals(a, b) { return a.equals(b); } if (b instanceof ParseObject) { - if (a.__type === "Object" || a.__type === "Pointer") { + if (a.__type === 'Object' || a.__type === 'Pointer') { return a.objectId === b.id && a.className === b.className; } } diff --git a/src/escape.js b/src/escape.js index eaa0ff15a..2445e6d2d 100644 --- a/src/escape.js +++ b/src/escape.js @@ -10,12 +10,12 @@ */ const encoded = { - "&": "&", - "<": "<", - ">": ">", - "/": "/", - "'": "'", - '"': """, + '&': '&', + '<': '<', + '>': '>', + '/': '/', + "'": ''', + '"': '"', }; export default function escape(str: string): string { diff --git a/src/interfaces/react-native.js b/src/interfaces/react-native.js index c124101fc..08b8a0e95 100644 --- a/src/interfaces/react-native.js +++ b/src/interfaces/react-native.js @@ -10,21 +10,11 @@ /** * 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; - static removeItem( - path: string, - cb: (err: string, value: string) => void - ): void; + static getItem(path: string, cb: (err: string, value: string) => void): void; + static setItem(path: string, value: string, cb: (err: string, value: string) => void): void; + static removeItem(path: string, cb: (err: string, value: string) => void): void; static getAllKeys(cb: (err: string, keys: Array) => void): void; static clear(): void; } diff --git a/src/isRevocableSession.js b/src/isRevocableSession.js index f0df86aca..a6a8a23b8 100644 --- a/src/isRevocableSession.js +++ b/src/isRevocableSession.js @@ -10,5 +10,5 @@ */ export default function isRevocableSession(token: string): boolean { - return token.indexOf("r:") > -1; + return token.indexOf('r:') > -1; } diff --git a/src/parseDate.js b/src/parseDate.js index bf50916d3..e6bde1a85 100644 --- a/src/parseDate.js +++ b/src/parseDate.js @@ -11,11 +11,11 @@ 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) { diff --git a/src/promiseUtils.js b/src/promiseUtils.js index 9be27de6c..176c32a0b 100644 --- a/src/promiseUtils.js +++ b/src/promiseUtils.js @@ -46,7 +46,7 @@ export function when(promises) { }; const chain = function (object, index) { - if (object && typeof object.then === "function") { + if (object && typeof object.then === 'function') { object.then( function (result) { results[index] = result; diff --git a/src/unique.js b/src/unique.js index 1b5d385f0..655a362f9 100644 --- a/src/unique.js +++ b/src/unique.js @@ -9,12 +9,12 @@ * @flow */ -import arrayContainsObject from "./arrayContainsObject"; -import ParseObject from "./ParseObject"; +import arrayContainsObject from './arrayContainsObject'; +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 5996a67af..6596e5a38 100644 --- a/src/unsavedChildren.js +++ b/src/unsavedChildren.js @@ -9,9 +9,9 @@ * @flow */ -import ParseFile from "./ParseFile"; -import ParseObject from "./ParseObject"; -import ParseRelation from "./ParseRelation"; +import ParseFile from './ParseFile'; +import ParseObject from './ParseObject'; +import ParseRelation from './ParseRelation'; type EncounterMap = { objects: { [identifier: string]: ParseObject | boolean }, @@ -34,11 +34,11 @@ export default function unsavedChildren( objects: {}, files: [], }; - const identifier = obj.className + ":" + obj._getId(); + const identifier = obj.className + ':' + obj._getId(); encountered.objects[identifier] = obj.dirty() ? obj : true; const attributes = obj.attributes; for (const attr in attributes) { - if (typeof attributes[attr] === "object") { + if (typeof attributes[attr] === 'object') { traverse(attributes[attr], encountered, false, !!allowDeepUnsaved); } } @@ -59,20 +59,15 @@ function traverse( ) { if (obj instanceof ParseObject) { if (!obj.id && shouldThrow) { - throw new Error("Cannot create a pointer to an unsaved Object."); + throw new Error('Cannot create a pointer to an unsaved Object.'); } - const identifier = obj.className + ":" + obj._getId(); + const identifier = obj.className + ':' + obj._getId(); if (!encountered.objects[identifier]) { encountered.objects[identifier] = obj.dirty() ? obj : true; const attributes = obj.attributes; for (const attr in attributes) { - if (typeof attributes[attr] === "object") { - traverse( - attributes[attr], - encountered, - !allowDeepUnsaved, - allowDeepUnsaved - ); + if (typeof attributes[attr] === 'object') { + traverse(attributes[attr], encountered, !allowDeepUnsaved, allowDeepUnsaved); } } } @@ -88,14 +83,14 @@ function traverse( return; } if (Array.isArray(obj)) { - obj.forEach((el) => { - if (typeof el === "object") { + obj.forEach(el => { + if (typeof el === 'object') { traverse(el, encountered, shouldThrow, allowDeepUnsaved); } }); } for (const k in obj) { - if (typeof obj[k] === "object") { + if (typeof obj[k] === 'object') { traverse(obj[k], encountered, shouldThrow, allowDeepUnsaved); } } From c134eedaa2089186aebf6857f70a8ad7b0fca408 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 12:54:53 +0100 Subject: [PATCH 04/11] fix --- src/ParseUser.js | 69 +++++++++++++++++++++++++++++---- src/__tests__/ParseUser-test.js | 4 +- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/ParseUser.js b/src/ParseUser.js index 65e6444f0..f0353d55f 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -623,26 +623,79 @@ class ParseUser extends ParseObject { return user.signUp({}, options); } - /** + /** * Logs in a user with a username (or email) and password. On success, this * saves the session to disk, so you can retrieve the currently logged in * user using current. * - * @param {string} username The username (or email) to log in with. - * @param {string} password The password to log in with. + * @param {string | object} usernameOrObject The username (or email) to log in with or an object with auth fields. + * @param {string | object} passwordOrOptions The password to log in with or options if usernameOrObject is an object. * @param {object} options * @static * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - 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.')); - } else if (typeof password !== 'string') { + static logIn( + usernameOrObject: string | Object, + passwordOrOptions: string | FullOptions, + options?: FullOptions + ) { + const usernameIsObject = typeof usernameOrObject === 'object'; + if (typeof usernameOrObject !== 'string') { + if (!usernameIsObject) { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Username must be a string or an object with username and password keys.' + ) + ); + } + if (typeof usernameOrObject.username !== 'string') { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Auth payload should contain username key with string value' + ) + ); + } + if (typeof usernameOrObject.password !== 'string') { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'Auth payload should contain password key with string value' + ) + ); + } + if (usernameOrObject.authData && typeof usernameOrObject.authData !== 'object') { + return Promise.reject( + new ParseError(ParseError.OTHER_CAUSE, 'authData should be an object') + ); + } + if ( + Object.keys(usernameOrObject).some( + key => !['authData', 'username', 'password'].includes(key) + ) + ) { + return Promise.reject( + new ParseError( + ParseError.OTHER_CAUSE, + 'This operation only support authData, username and password keys' + ) + ); + } + } + if (typeof passwordOrOptions !== 'string' && !usernameIsObject) { return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } const user = new this(); - user._finishFetch({ username: username, password: password }); + user._finishFetch( + usernameIsObject + ? usernameOrObject + : { + username: usernameOrObject, + password: passwordOrOptions, + } + ); return user.logIn(options); } diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index 1b8450dc0..03713d71a 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -322,12 +322,12 @@ describe('ParseUser', () => { it('fail login when invalid username or password is used', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); - ParseUser.logIn({}, 'password') + ParseUser.logIn(undefined, 'password') .then(null, err => { expect(err.code).toBe(ParseError.OTHER_CAUSE); expect(err.message).toBe('Username must be a string.'); - return ParseUser.logIn('username', {}); + return ParseUser.logIn('username', undefined); }) .then(null, err => { expect(err.code).toBe(ParseError.OTHER_CAUSE); From 9800f91c76bfbdeb946e294a654dfe67bfec7c9a Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 12:59:42 +0100 Subject: [PATCH 05/11] fix --- package-lock.json | 898 ++++++++++++++++++++++++++++++-- src/__tests__/ParseUser-test.js | 18 - 2 files changed, 845 insertions(+), 71 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7be0da87b..dea5ea052 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2039,6 +2039,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", @@ -2221,6 +2227,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", @@ -3819,6 +3835,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-color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", @@ -3851,6 +3873,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", @@ -4087,6 +4162,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", @@ -4242,6 +4323,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", @@ -4636,6 +4750,12 @@ } } }, + "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", @@ -5287,6 +5407,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", @@ -6279,6 +6416,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", @@ -6598,6 +6744,12 @@ "which": "^1.1.1" } }, + "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-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -6877,6 +7029,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": { @@ -7564,6 +7724,124 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "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": { + "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", @@ -7620,6 +7898,12 @@ "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", @@ -8019,6 +8303,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-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", @@ -8067,6 +8357,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", @@ -9094,6 +9390,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", @@ -9362,6 +9664,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", @@ -9371,58 +9679,336 @@ "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.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", - "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.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, + "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.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", + "dev": true + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", + "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.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, "lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", @@ -9561,6 +10147,141 @@ "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=", "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", @@ -10921,6 +11642,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", @@ -11028,6 +11755,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", @@ -12181,6 +12917,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", @@ -12220,6 +12962,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", @@ -12302,9 +13053,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": { @@ -13230,6 +13981,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", @@ -13239,6 +13996,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", @@ -14049,6 +14812,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", @@ -14183,6 +14952,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", @@ -15391,6 +16171,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", @@ -15668,6 +16454,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/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index 03713d71a..7a5907e3d 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -319,24 +319,6 @@ describe('ParseUser', () => { }); }); - it('fail login when invalid username or password is used', done => { - ParseUser.enableUnsafeCurrentUser(); - ParseUser._clearCache(); - ParseUser.logIn(undefined, 'password') - .then(null, err => { - expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe('Username must be a string.'); - - return ParseUser.logIn('username', undefined); - }) - .then(null, err => { - expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe('Password must be a string.'); - - done(); - }); - }); - it('fail login when invalid username or password is used', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); From a89d420701ed01ab4d0ad4bab2da22f8699a9e8c Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 13:04:26 +0100 Subject: [PATCH 06/11] fix test --- src/ParseUser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ParseUser.js b/src/ParseUser.js index f0353d55f..0e895f5fa 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -1131,6 +1131,7 @@ const DefaultController = { const auth = { username: user.get('username'), password: user.get('password'), + authData: user.get('authData'), }; return RESTController.request(options.usePost ? 'POST' : 'GET', 'login', auth, options).then( response => { From dc3d24bf3ce1b8801e01970700f2b25acc48fcd8 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 13:09:41 +0100 Subject: [PATCH 07/11] fix lint --- src/ParseUser.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ParseUser.js b/src/ParseUser.js index 0e895f5fa..cbb55e61f 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -623,7 +623,7 @@ class ParseUser extends ParseObject { return user.signUp({}, options); } - /** + /** * Logs in a user with a username (or email) and password. On success, this * saves the session to disk, so you can retrieve the currently logged in * user using current. @@ -692,9 +692,9 @@ class ParseUser extends ParseObject { usernameIsObject ? usernameOrObject : { - username: usernameOrObject, - password: passwordOrOptions, - } + username: usernameOrObject, + password: passwordOrOptions, + } ); return user.logIn(options); } From 67bc770a0a7c8e675ed4ed2390d2c353cc5d8a8e Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 13:16:04 +0100 Subject: [PATCH 08/11] fix flaky test --- integration/test/ParseObjectTest.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 777b1d5cb..c31da08d8 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -268,9 +268,9 @@ describe('Parse Object', () => { const startDiff = Math.abs(start.getTime() - object.createdAt.getTime()); const endDiff = Math.abs(end.getTime() - object.createdAt.getTime()); expect(startDiff).toBeLessThan(500); - expect(startDiff).toBeGreaterThan(0); + expect(startDiff).toBeGreaterThanOrEqual(0); expect(endDiff).toBeLessThan(500); - expect(endDiff).toBeGreaterThan(0); + expect(endDiff).toBeGreaterThanOrEqual(0); done(); }); }); From c3fa1e80da623e35a89c64174bcb268a18ed6484 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Fri, 11 Dec 2020 15:20:30 +0100 Subject: [PATCH 09/11] swith to POST if authData detected --- src/ParseUser.js | 31 +++++++++++++++++-------------- src/__tests__/ParseUser-test.js | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/ParseUser.js b/src/ParseUser.js index cbb55e61f..0718a7424 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -1133,21 +1133,24 @@ const DefaultController = { password: user.get('password'), authData: user.get('authData'), }; - 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 RESTController.request( + options.usePost || auth.authData ? '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); + }); }, become(user: ParseUser, options: RequestOptions): Promise { diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index 7a5907e3d..28551f00b 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -385,7 +385,7 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request(method, path, body) { - expect(method).toBe('GET'); + expect(method).toBe('POST'); expect(path).toBe('login'); expect(body.username).toBe('username'); expect(body.password).toBe('password'); From 80fb9bcd4540490ccafba9a8151751e03b62d9b6 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 14 Dec 2020 18:27:25 +0100 Subject: [PATCH 10/11] restore lock --- package-lock.json | 1723 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1722 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 4774c875f..2566b8b87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1535,6 +1535,21 @@ "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==", "dev": true }, + "@hapi/hoek": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.0.tgz", + "integrity": "sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==", + "dev": true + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@jest/console": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", @@ -2068,6 +2083,27 @@ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=", "dev": true }, + "@sideway/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.0.tgz", + "integrity": "sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -2552,6 +2588,81 @@ "uri-js": "^4.2.2" } }, + "ampersand-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz", + "integrity": "sha1-9AK8LhgwX6vZldvc07cFe73X00c=", + "dev": true, + "requires": { + "ampersand-version": "^1.0.2", + "lodash": "^4.6.1" + } + }, + "ampersand-state": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz", + "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==", + "dev": true, + "requires": { + "ampersand-events": "^2.0.1", + "ampersand-version": "^1.0.0", + "array-next": "~0.0.1", + "key-tree-store": "^1.3.0", + "lodash": "^4.12.0" + } + }, + "ampersand-version": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz", + "integrity": "sha1-/489TOrE0yzNg/a9Zpc5f3tZ4sA=", + "dev": true, + "requires": { + "find-root": "^0.1.1", + "through2": "^0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", + "dev": true + }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -3033,6 +3144,12 @@ } } }, + "array-next": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz", + "integrity": "sha1-5eRmCkwn/agVH/d2QnXQCQAGK+E=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -3639,6 +3756,12 @@ } } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3907,6 +4030,28 @@ "ieee754": "^1.1.4" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", @@ -3919,6 +4064,12 @@ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", "dev": true }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4073,6 +4224,18 @@ "lodash": "^4.17.14" } }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "dev": true, + "requires": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4090,6 +4253,36 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -4184,6 +4377,29 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli-color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", + "integrity": "sha1-dfpfcowwjMSsWUsF4GzF2A2szYY=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.2", + "memoizee": "0.3.x", + "timers-ext": "0.1.x" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4329,6 +4545,15 @@ "readable-stream": "^2.3.5" } }, + "clui": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz", + "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==", + "dev": true, + "requires": { + "cli-color": "0.3.2" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4509,6 +4734,22 @@ "typedarray": "^0.0.6" } }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "connected-domain": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", + "integrity": "sha1-v+dyOMdL5FOnnwy2BY3utPI1jpM=", + "dev": true + }, "console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -4801,6 +5042,24 @@ "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", "optional": true }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, "cssfilter": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", @@ -4904,6 +5163,135 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dev": true, + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dev": true, + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "dev": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dev": true, + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -5295,6 +5683,12 @@ } } }, + "docopt": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", + "integrity": "sha1-so6eIiDaXsSffqW7JKR3h0Be6xE=", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5304,12 +5698,28 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", @@ -5319,6 +5729,108 @@ "webidl-conversions": "^4.0.2" } }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "downcache": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/downcache/-/downcache-0.0.9.tgz", + "integrity": "sha1-eQuwQkaJE2EVzpPyqhWUbG2AbQ4=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "graceful-fs": "^4.1.3", + "limiter": "^1.1.0", + "mkdirp": "^0.5.1", + "npmlog": "^2.0.3", + "request": "^2.69.0", + "rimraf": "^2.5.2" + }, + "dependencies": { + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "dev": true, + "requires": { + "ansi": "^0.3.0", + "has-unicode": "^2.0.0", + "lodash.pad": "^4.1.0", + "lodash.padend": "^4.1.0", + "lodash.padstart": "^4.1.0" + } + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "dev": true, + "requires": { + "ansi": "~0.3.1", + "are-we-there-yet": "~1.1.2", + "gauge": "~1.2.5" + } + } + } + }, + "download": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", + "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", + "dev": true, + "requires": { + "caw": "^2.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.0.0", + "ext-name": "^5.0.0", + "file-type": "5.2.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^7.0.0", + "make-dir": "^1.0.0", + "p-event": "^1.0.0", + "pify": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + } + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -5328,6 +5840,12 @@ "readable-stream": "^2.0.2" } }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -5845,6 +6363,21 @@ "es5-ext": "~0.10.14" } }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -6090,6 +6623,25 @@ } } }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6250,6 +6802,15 @@ "bser": "2.1.1" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "fecha": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", @@ -6283,6 +6844,12 @@ "moment": "^2.11.2" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "dev": true + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -6295,6 +6862,23 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "dev": true + }, + "filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -6350,6 +6934,12 @@ } } }, + "find-root": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz", + "integrity": "sha1-mNImfP8ZFsyvJ0OzoO6oHXnX3NE=", + "dev": true + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -6500,12 +7090,35 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, "fs-capacitor": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-mkdirp-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", @@ -6663,12 +7276,33 @@ "has-symbols": "^1.0.1" } }, + "get-mongodb-version": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-2.0.1.tgz", + "integrity": "sha512-yTN0UY7VJSSt01QH/aCiqiBjfxcDrEdKeM3uXY6QR3sRARoftx36QT0YNsCQm7FDTgrmDje7bK2C9ClM7SGKDA==", + "dev": true, + "requires": { + "lodash.startswith": "^4.2.1", + "minimist": "^1.1.1", + "mongodb": "*", + "which": "^1.1.1" + } + }, "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-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "dev": true, + "requires": { + "npm-conf": "^1.1.0" + } + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -6884,6 +7518,36 @@ "sparkles": "^1.0.0" } }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "requires": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -7360,12 +8024,27 @@ "sparkles": "^1.0.0" } }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -7500,6 +8179,33 @@ "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -8064,6 +8770,39 @@ "is-extglob": "^2.1.1" } }, + "is-mongodb-running": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-1.0.2.tgz", + "integrity": "sha512-EslN8MErcBPExb+iK4RnG1n28JGjByA2Rm3YPmdHDGCRd7Hc2uvqshyVMAJXxbDSxRMy8vhxims2oRqQUeGJeA==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "debug": ">= 2.6.9", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "lsof": "^0.1.0", + "minimist": "^1.2.0", + "node-netstat": "^1.4.2", + "ps-node": "^0.1.6" + }, + "dependencies": { + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + } + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "dev": true + }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -8102,6 +8841,18 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -8153,6 +8904,12 @@ "is-unc-path": "^1.0.0" } }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -8312,6 +9069,16 @@ "html-escaper": "^2.0.0" } }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, "iterall": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", @@ -8996,6 +9763,19 @@ "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", "dev": true }, + "joi": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.3.0.tgz", + "integrity": "sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9190,6 +9970,15 @@ "minimist": "^1.2.5" } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -9289,6 +10078,12 @@ "safe-buffer": "^5.0.1" } }, + "key-tree-store": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz", + "integrity": "sha1-XqKa/CUppCWThDfWlVtxTOapeR8=", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -9336,6 +10131,12 @@ "es6-weak-map": "^2.0.1" } }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -9756,12 +10557,54 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", + "dev": true + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", + "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.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", + "dev": true + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -9798,24 +10641,84 @@ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", "dev": true }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "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 }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "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 }, + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", + "dev": true + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.startswith": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", + "integrity": "sha1-xZjErc4YiiflMUVzHNxsDnF3YAw=", + "dev": true + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -10002,6 +10905,12 @@ } } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -10039,6 +10948,21 @@ } } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "lsof": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz", + "integrity": "sha1-rALU2HYGIB8TZLr7FcSRz9WuMJI=", + "dev": true + }, "mailgun-js": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.0.tgz", @@ -10130,6 +11054,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -10228,6 +11158,71 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "memoizee": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", + "integrity": "sha1-TsoNiu057J0Bf0xcLy9kMvQuXI8=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.11", + "es6-weak-map": "~0.1.4", + "event-emitter": "~0.3.4", + "lru-queue": "0.1", + "next-tick": "~0.2.2", + "timers-ext": "0.1" + }, + "dependencies": { + "d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5", + "es6-symbol": "~2.0.1" + } + }, + "es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.5" + } + }, + "es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "dev": true, + "requires": { + "d": "~0.1.1", + "es5-ext": "~0.10.6", + "es6-iterator": "~0.1.3", + "es6-symbol": "~2.0.1" + } + }, + "next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=", + "dev": true + } + } + }, "memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -10365,6 +11360,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -10482,6 +11483,304 @@ "saslprep": "^1.0.0" } }, + "mongodb-core": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.7.tgz", + "integrity": "sha512-WypKdLxFNPOH/Jy6i9z47IjG2wIldA54iDZBmHMINcgKOUcWJh8og+Wix76oGd7EyYkHJKssQ2FAOw5Su/n4XQ==", + "dev": true, + "requires": { + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "mongodb-dbpath": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz", + "integrity": "sha1-4BMsZ3sbncgwBFEW0Yrbf2kk8XU=", + "dev": true, + "requires": { + "async": "^1.4.0", + "debug": "^2.1.1", + "minimist": "^1.1.1", + "mkdirp": "^0.5.1", + "untildify": "^1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "untildify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz", + "integrity": "sha1-TYAx0YBvT718QrAjeq8hNoYmJjU=", + "dev": true, + "requires": { + "user-home": "^1.0.0" + } + } + } + }, + "mongodb-download-url": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-0.5.2.tgz", + "integrity": "sha512-hEwWEsJUh/XbY8yy7EfwF4a6Hres/v89EyMV5/l3dWh8zT2isIo9gt94RkLgvdgOliBw4jtGbViIOcvM6F1G/w==", + "dev": true, + "requires": { + "async": "^2.1.2", + "debug": "^2.2.0", + "lodash.defaults": "^4.0.0", + "minimist": "^1.2.0", + "mongodb-version-list": "^1.0.0", + "request": "^2.65.0", + "semver": "^5.0.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "mongodb-runner": { + "version": "github:mongodb-js/runner#dfb9a520147de6e2537f7c1c21a5e7005d1905f8", + "from": "github:mongodb-js/runner", + "dev": true, + "requires": { + "async": "^3.1.0", + "clui": "^0.3.6", + "debug": "^4.1.1", + "fs-extra": "^8.1.0", + "is-mongodb-running": "^1.0.1", + "lodash.defaults": "^4.2.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "mongodb": "^3.4.0", + "mongodb-dbpath": "^0.0.1", + "mongodb-tools": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", + "mongodb-version-manager": "^1.4.3", + "untildify": "^4.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "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" + } + } + } + }, + "mongodb-tools": { + "version": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", + "from": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", + "dev": true, + "requires": { + "debug": "^2.2.0", + "lodash": "^4.17.12", + "mkdirp": "0.5.0", + "mongodb-core": "*", + "rimraf": "2.2.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "rimraf": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", + "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=", + "dev": true + } + } + }, + "mongodb-version-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mongodb-version-list/-/mongodb-version-list-1.0.0.tgz", + "integrity": "sha1-8lAxz83W8UWx3o/OKk6+wCiLtKQ=", + "dev": true, + "requires": { + "cheerio": "^0.22.0", + "debug": "^2.2.0", + "downcache": "^0.0.9", + "fs-extra": "^1.0.0", + "minimist": "^1.1.1", + "semver": "^5.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "mongodb-version-manager": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.4.3.tgz", + "integrity": "sha512-+zQdWHLdumqX4mNyqLP08LIa8Wsn52AyU8lEBRx4onlCN13AVNCvgHtCjBAquCYC/wm1rT1i7nAglSJq1LD81Q==", + "dev": true, + "requires": { + "ampersand-state": "^5.0.3", + "async": "^2.1.2", + "chalk": "^2.1.0", + "debug": ">= 2.6.9 < 3.0.0 || >= ^3.1.0", + "docopt": "^0.6.2", + "download": "^6.2.5", + "figures": "^2.0.0", + "fs-extra": "^4.0.2", + "get-mongodb-version": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.1.1", + "mongodb-download-url": "^0.5.2", + "mongodb-version-list": "^1.0.0", + "semver": "^5.3.0", + "tildify": "^1.2.0", + "untildify": "^3.0.2" + }, + "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" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -10598,6 +11897,15 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, + "node-netstat": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-netstat/-/node-netstat-1.8.0.tgz", + "integrity": "sha512-P1a5Sh9FfjTXxI6hC9q/Nqre8kT63FQxBCr1qz5ffk76EkQBH62+XEhIhlzfz6Bz+FRwOFqidW2FDGXnOXvyJQ==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, "node-notifier": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", @@ -10647,6 +11955,16 @@ "once": "^1.3.2" } }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -10668,6 +11986,15 @@ "set-blocking": "~2.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -10943,6 +12270,12 @@ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", @@ -10958,6 +12291,12 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true + }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", @@ -10967,6 +12306,15 @@ "p-reduce": "^1.0.0" } }, + "p-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", + "integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=", + "dev": true, + "requires": { + "p-timeout": "^1.1.1" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -11006,6 +12354,15 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -11254,7 +12611,7 @@ "dev": true }, "parse-server": { - "version": "github:parse-community/parse-server#43d9af847bdd66c2cc09a2f293c34534a7c042bd", + "version": "github:parse-community/parse-server#06cb79e6a595aefc05f3c4d28f6edcba607f39f5", "from": "github:parse-community/parse-server#master", "dev": true, "requires": { @@ -11466,6 +12823,15 @@ "pify": "^3.0.0" } }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, "pbkdf2": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", @@ -11479,6 +12845,12 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -11723,6 +13095,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -11809,6 +13187,12 @@ "react-is": "^16.8.1" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -11914,6 +13298,24 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "ps-node": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", + "integrity": "sha1-mvZ6mdex0BMuUaUDCZ04qNKs4sM=", + "dev": true, + "requires": { + "table-parser": "^0.1.3" + } + }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -12619,6 +14021,23 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dev": true, + "requires": { + "commander": "^2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -13014,6 +14433,24 @@ } } }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dev": true, + "requires": { + "sort-keys": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -13111,6 +14548,15 @@ "integrity": "sha512-ZNCrOso+oNv5P01HCO4wuxV9Og5rS6ms7gGAqugfBPjx1QwfNXJI3T02ldfaap1O0dlT1sB0Rk+mhDqxt3Z27w==", "dev": true }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -13188,6 +14634,112 @@ } } }, + "start-server-and-test": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.11.6.tgz", + "integrity": "sha512-+0T83W/R7CVgIE2HJcrpJDleLt7Skc2Xj8jWWsItRGdpZwenAv0YtIpBEKoL64pwUtPAPoHuYUtvWUOfCRoVjg==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.3.1", + "execa": "3.4.0", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "5.2.0" + }, + "dependencies": { + "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": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "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", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "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" + } + }, + "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 + }, + "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" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "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 + }, + "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" + } + } + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -13231,6 +14783,15 @@ "readable-stream": "^2.0.2" } }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, "stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", @@ -13491,6 +15052,15 @@ } } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dev": true, + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -13509,6 +15079,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", @@ -13631,12 +15210,48 @@ } } }, + "table-parser": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", + "integrity": "sha1-BEHPzhallIFoTCfRtaZ/8VpDx7A=", + "dev": true, + "requires": { + "connected-domain": "^1.0.0" + } + }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", "dev": true }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + } + } + }, "teeny-request": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", @@ -13712,12 +15327,27 @@ "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", "dev": true }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, "timers-browserify": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", @@ -13727,6 +15357,16 @@ "process": "~0.11.0" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -13752,6 +15392,12 @@ "is-negated-glob": "^1.0.0" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -13850,6 +15496,15 @@ } } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -13965,6 +15620,16 @@ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", "dev": true }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -14072,6 +15737,12 @@ "through2-filter": "^3.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -14118,6 +15789,12 @@ } } }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, "upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -14165,6 +15842,21 @@ } } }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, "urlgrey": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", @@ -14177,6 +15869,12 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, "util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -14428,6 +16126,19 @@ "browser-process-hrtime": "^1.0.0" } }, + "wait-on": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.2.0.tgz", + "integrity": "sha512-U1D9PBgGw2XFc6iZqn45VBubw02VsLwnZWteQ1au4hUVHasTZuFSKRzlTB2dqgLhji16YVI8fgpEpwUdCr8B6g==", + "dev": true, + "requires": { + "axios": "^0.19.2", + "joi": "^17.1.1", + "lodash": "^4.17.19", + "minimist": "^1.2.5", + "rxjs": "^6.5.5" + } + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -14935,6 +16646,16 @@ "object.assign": "^4.1.0" } }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", From 8ad13a3e4ab8ce7653ffaef1e550cfb78ae3aaae Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Tue, 15 Dec 2020 12:24:37 +0100 Subject: [PATCH 11/11] Add challenge endpoint --- src/ParseUser.js | 30 ++++++++++++++++++++++ src/__tests__/ParseUser-test.js | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/ParseUser.js b/src/ParseUser.js index 0718a7424..19f459991 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -782,6 +782,32 @@ class ParseUser extends ParseObject { return user.linkWith(provider, options, saveOpts); } + /** + * Ask Parse server for an auth challenge (ex: WebAuthn login/signup) + * + * @param data + * @static + * @returns {Promise} + */ + static challenge(data: { + authData?: AuthData, + username?: string, + password?: string, + challengeData: any, + }): Promise<{ challengeData: any }> { + if (!data.challengeData) { + return Promise.reject( + new ParseError(ParseError.OTHER_CAUSE, 'challengeData is required for the challenge.') + ); + } + if (data.username && !data.password) { + return Promise.reject( + new ParseError(ParseError.OTHER_CAUSE, 'Running challenge via username require password.') + ); + } + return CoreManager.getUserController().challenge(data); + } + /** * Logs out the currently logged in user session. This will remove the * session from disk, log out of linked services, and future calls to @@ -1153,6 +1179,10 @@ const DefaultController = { }); }, + challenge(data: any): Promise<{ challengeData: any }> { + return CoreManager.getRESTController().request('POST', 'challenge', data); + }, + become(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); return RESTController.request('GET', 'users/me', {}, options).then(response => { diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index 28551f00b..86ae12d27 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -1881,4 +1881,49 @@ describe('ParseUser', () => { const user = new CustomUser(); expect(user.test).toBe(true); }); + + it('should return challenge', async () => { + ParseUser.enableUnsafeCurrentUser(); + ParseUser._clearCache(); + CoreManager.setRESTController({ + request(method, path, body) { + expect(method).toBe('POST'); + expect(path).toBe('challenge'); + expect(body.username).toBe('username'); + expect(body.password).toBe('password'); + expect(body.challengeData).toEqual({ test: { data: true } }); + + return Promise.resolve( + { + challengeData: { test: { token: true } }, + }, + 200 + ); + }, + ajax() {}, + }); + + try { + await ParseUser.challenge({ + username: 'username', + challengeData: { test: { data: true } }, + }); + } catch (e) { + expect(e.message).toContain('Running challenge via username require password.'); + } + + try { + await ParseUser.challenge({}); + } catch (e) { + expect(e.message).toContain('challengeData is required for the challenge.'); + } + + const res = await ParseUser.challenge({ + username: 'username', + password: 'password', + challengeData: { test: { data: true } }, + }); + + expect(res.challengeData).toEqual({ test: { token: true } }); + }); });