1008 lines
42 KiB
JavaScript
1008 lines
42 KiB
JavaScript
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright 2016 Realm Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
'use strict';
|
|
|
|
const Realm = require('realm');
|
|
let TestCase = require('./asserts');
|
|
let schemas = require('./schemas');
|
|
|
|
const DATA1 = new Uint8Array([0x01]);
|
|
const DATA2 = new Uint8Array([0x02]);
|
|
const DATA3 = new Uint8Array([0x03]);
|
|
const DATE1 = new Date(1);
|
|
const DATE2 = new Date(2);
|
|
const DATE3 = new Date(3);
|
|
|
|
module.exports = {
|
|
testListConstructor: function() {
|
|
const realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('PersonList', {list: []});
|
|
TestCase.assertInstanceOf(obj.list, Realm.List);
|
|
TestCase.assertInstanceOf(obj.list, Realm.Collection);
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => new Realm.List(), 'constructor');
|
|
|
|
TestCase.assertType(Realm.List, 'function');
|
|
TestCase.assertInstanceOf(Realm.List, Function);
|
|
},
|
|
|
|
testListType: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject, schemas.PrimitiveArrays]});
|
|
|
|
let obj, prim;
|
|
realm.write(() => {
|
|
obj = realm.create('LinkTypesObject', {});
|
|
prim = realm.create('PrimitiveArrays', {});
|
|
});
|
|
|
|
TestCase.assertEqual(obj.arrayCol.type, 'object');
|
|
TestCase.assertEqual(obj.arrayCol1.type, 'object');
|
|
|
|
TestCase.assertEqual(prim.bool.type, 'bool');
|
|
TestCase.assertEqual(prim.int.type, 'int');
|
|
TestCase.assertEqual(prim.float.type, 'float');
|
|
TestCase.assertEqual(prim.double.type, 'double');
|
|
TestCase.assertEqual(prim.string.type, 'string');
|
|
TestCase.assertEqual(prim.date.type, 'date');
|
|
TestCase.assertEqual(prim.optBool.type, 'bool');
|
|
TestCase.assertEqual(prim.optInt.type, 'int');
|
|
TestCase.assertEqual(prim.optFloat.type, 'float');
|
|
TestCase.assertEqual(prim.optDouble.type, 'double');
|
|
TestCase.assertEqual(prim.optString.type, 'string');
|
|
TestCase.assertEqual(prim.optDate.type, 'date');
|
|
|
|
TestCase.assertFalse(prim.bool.optional);
|
|
TestCase.assertFalse(prim.int.optional);
|
|
TestCase.assertFalse(prim.float.optional);
|
|
TestCase.assertFalse(prim.double.optional);
|
|
TestCase.assertFalse(prim.string.optional);
|
|
TestCase.assertFalse(prim.date.optional);
|
|
TestCase.assertTrue(prim.optBool.optional);
|
|
TestCase.assertTrue(prim.optInt.optional);
|
|
TestCase.assertTrue(prim.optFloat.optional);
|
|
TestCase.assertTrue(prim.optDouble.optional);
|
|
TestCase.assertTrue(prim.optString.optional);
|
|
TestCase.assertTrue(prim.optDate.optional);
|
|
},
|
|
|
|
testListLength: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
TestCase.assertEqual(array.length, 1);
|
|
|
|
obj.arrayCol = [];
|
|
TestCase.assertEqual(array.length, 0);
|
|
|
|
obj.arrayCol = [{doubleCol: 1}, {doubleCol: 2}];
|
|
TestCase.assertEqual(array.length, 2);
|
|
|
|
TestCase.assertThrowsContaining(() => array.length = 0,
|
|
"Cannot assign to read only property 'length'");
|
|
});
|
|
|
|
TestCase.assertEqual(array.length, 2);
|
|
},
|
|
|
|
testListSubscriptGetters: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject, schemas.PrimitiveArrays]});
|
|
let obj, prim;
|
|
|
|
realm.write(() => {
|
|
obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
arrayCol1: [{doubleCol: 5}, {doubleCol: 6}],
|
|
});
|
|
prim = realm.create('PrimitiveArrays', {
|
|
bool: [true, false],
|
|
int: [1, 2],
|
|
float: [1.1, 2.2],
|
|
double: [1.11, 2.22],
|
|
string: ['a', 'b'],
|
|
date: [new Date(1), new Date(2)],
|
|
data: [DATA1, DATA2],
|
|
|
|
optBool: [true, null],
|
|
optInt: [1, null],
|
|
optFloat: [1.1, null],
|
|
optDouble: [1.11, null],
|
|
optString: ['a', null],
|
|
optDate: [new Date(1), null],
|
|
optData: [DATA1, null],
|
|
});
|
|
});
|
|
|
|
TestCase.assertEqual(obj.arrayCol[0].doubleCol, 3);
|
|
TestCase.assertEqual(obj.arrayCol[1].doubleCol, 4);
|
|
TestCase.assertEqual(obj.arrayCol[2], undefined);
|
|
TestCase.assertEqual(obj.arrayCol[-1], undefined);
|
|
TestCase.assertEqual(obj.arrayCol['foo'], undefined);
|
|
|
|
TestCase.assertEqual(obj.arrayCol1[0].doubleCol, 5);
|
|
TestCase.assertEqual(obj.arrayCol1[1].doubleCol, 6);
|
|
TestCase.assertEqual(obj.arrayCol1[2], undefined);
|
|
TestCase.assertEqual(obj.arrayCol1[-1], undefined);
|
|
TestCase.assertEqual(obj.arrayCol1['foo'], undefined);
|
|
|
|
for (let field of Object.keys(prim)) {
|
|
TestCase.assertEqual(prim[field][2], undefined);
|
|
TestCase.assertEqual(prim[field][-1], undefined);
|
|
TestCase.assertEqual(prim[field]['foo'], undefined);
|
|
if (field.includes('opt')) {
|
|
TestCase.assertEqual(prim[field][1], null);
|
|
}
|
|
}
|
|
|
|
TestCase.assertSimilar('bool', prim.bool[0], true);
|
|
TestCase.assertSimilar('bool', prim.bool[1], false);
|
|
TestCase.assertSimilar('int', prim.int[0], 1);
|
|
TestCase.assertSimilar('int', prim.int[1], 2);
|
|
TestCase.assertSimilar('float', prim.float[0], 1.1);
|
|
TestCase.assertSimilar('float', prim.float[1], 2.2);
|
|
TestCase.assertSimilar('double', prim.double[0], 1.11);
|
|
TestCase.assertSimilar('double', prim.double[1], 2.22);
|
|
TestCase.assertSimilar('string', prim.string[0], 'a');
|
|
TestCase.assertSimilar('string', prim.string[1], 'b');
|
|
TestCase.assertSimilar('data', prim.data[0], DATA1);
|
|
TestCase.assertSimilar('data', prim.data[1], DATA2);
|
|
TestCase.assertSimilar('date', prim.date[0], new Date(1));
|
|
TestCase.assertSimilar('date', prim.date[1], new Date(2));
|
|
|
|
TestCase.assertSimilar('bool', prim.optBool[0], true);
|
|
TestCase.assertSimilar('int', prim.optInt[0], 1);
|
|
TestCase.assertSimilar('float', prim.optFloat[0], 1.1);
|
|
TestCase.assertSimilar('double', prim.optDouble[0], 1.11);
|
|
TestCase.assertSimilar('string', prim.optString[0], 'a');
|
|
TestCase.assertSimilar('data', prim.optData[0], DATA1);
|
|
TestCase.assertSimilar('date', prim.optDate[0], new Date(1));
|
|
},
|
|
|
|
testListSubscriptSetters: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject,
|
|
schemas.PrimitiveArrays]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
let prim = realm.create('PrimitiveArrays', {});
|
|
array = obj.arrayCol;
|
|
|
|
array[0] = {doubleCol: 5};
|
|
array[1] = {doubleCol: 6};
|
|
TestCase.assertEqual(array[0].doubleCol, 5);
|
|
TestCase.assertEqual(array[1].doubleCol, 6);
|
|
|
|
array[0] = obj.objectCol;
|
|
array[1] = obj.objectCol1;
|
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
|
TestCase.assertEqual(array[1].doubleCol, 2);
|
|
|
|
TestCase.assertThrowsContaining(() => array[0] = null,
|
|
"JS value must be of type 'object', got (null)");
|
|
TestCase.assertThrowsContaining(() => array[0] = {},
|
|
"Missing value for property 'TestObject.doubleCol'");
|
|
TestCase.assertThrowsContaining(() => array[0] = {foo: 'bar'},
|
|
"Missing value for property 'TestObject.doubleCol'");
|
|
TestCase.assertThrowsContaining(() => array[0] = prim,
|
|
"Object of type (PrimitiveArrays) does not match List type (TestObject)");
|
|
TestCase.assertThrowsContaining(() => array[0] = array,
|
|
"Missing value for property 'TestObject.doubleCol'");
|
|
TestCase.assertThrowsContaining(() => array[2] = {doubleCol: 1},
|
|
"Requested index 2 greater than max 1");
|
|
TestCase.assertThrowsContaining(() => array[-1] = {doubleCol: 1},
|
|
"Index -1 cannot be less than zero.");
|
|
|
|
array['foo'] = 'bar';
|
|
TestCase.assertEqual(array.foo, 'bar');
|
|
|
|
function testAssign(name, v1, v2) {
|
|
prim[name].push(v1);
|
|
TestCase.assertSimilar(prim[name].type, prim[name][0], v1, undefined, 1);
|
|
prim[name][0] = v2;
|
|
TestCase.assertSimilar(prim[name].type, prim[name][0], v2, undefined, 1);
|
|
}
|
|
|
|
testAssign('bool', true, false);
|
|
testAssign('int', 1, 2);
|
|
testAssign('float', 1.1, 2.2);
|
|
testAssign('double', 1.1, 2.2);
|
|
testAssign('string', 'a', 'b');
|
|
testAssign('data', DATA1, DATA2);
|
|
testAssign('date', DATE1, DATE2);
|
|
|
|
function testAssignNull(name, expected) {
|
|
TestCase.assertThrowsContaining(() => prim[name][0] = null,
|
|
`Property must be of type '${expected}', got (null)`,
|
|
undefined, 1);
|
|
}
|
|
|
|
testAssignNull('bool', 'bool');
|
|
testAssignNull('int', 'int');
|
|
testAssignNull('float', 'float');
|
|
testAssignNull('double', 'double');
|
|
testAssignNull('string', 'string');
|
|
testAssignNull('data', 'data');
|
|
testAssignNull('date', 'date');
|
|
|
|
testAssign('optBool', true, null);
|
|
testAssign('optInt', 1, null);
|
|
testAssign('optFloat', 1.1, null);
|
|
testAssign('optDouble', 1.1, null);
|
|
testAssign('optString', 'a', null);
|
|
testAssign('optData', DATA1, null);
|
|
testAssign('optDate', DATE1, null);
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => array[0] = {doubleCol: 1},
|
|
"Cannot modify managed objects outside of a write transaction.");
|
|
|
|
array['foo'] = 'baz';
|
|
TestCase.assertEqual(array.foo, 'baz');
|
|
},
|
|
|
|
testListAssignment: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject,
|
|
schemas.PersonList, schemas.PersonObject,
|
|
schemas.PrimitiveArrays]});
|
|
|
|
let obj, prim;
|
|
realm.write(() => {
|
|
obj = realm.create('LinkTypesObject', {});
|
|
prim = realm.create('PrimitiveArrays', {});
|
|
let person = realm.create('PersonObject', {name: 'a', age: 2.0});
|
|
let personList = realm.create('PersonList', {list: [person]}).list;
|
|
|
|
TestCase.assertThrowsContaining(() => obj.arrayCol = [0],
|
|
"JS value must be of type 'object', got (0)");
|
|
TestCase.assertThrowsContaining(() => obj.arrayCol = [null],
|
|
"JS value must be of type 'object', got (null)");
|
|
TestCase.assertThrowsContaining(() => obj.arrayCol = [person],
|
|
"Object of type (PersonObject) does not match List type (TestObject)");
|
|
TestCase.assertThrowsContaining(() => obj.arrayCol = personList,
|
|
"LinkTypesObject.arrayCol must be of type 'TestObject[]', got 'object' (");
|
|
obj.arrayCol = [realm.create('TestObject', {doubleCol: 1.0})]
|
|
TestCase.assertEqual(obj.arrayCol[0].doubleCol, 1.0);
|
|
obj.arrayCol = obj.arrayCol;
|
|
TestCase.assertEqual(obj.arrayCol[0].doubleCol, 1.0);
|
|
|
|
TestCase.assertThrowsContaining(() => prim.bool = [person],
|
|
"PrimitiveArrays.bool must be of type 'boolean[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.int = [person],
|
|
"PrimitiveArrays.int must be of type 'number[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.float = [person],
|
|
"PrimitiveArrays.float must be of type 'number[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.double = [person],
|
|
"PrimitiveArrays.double must be of type 'number[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.string = [person],
|
|
"PrimitiveArrays.string must be of type 'string[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.data = [person],
|
|
"PrimitiveArrays.data must be of type 'binary[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.date = [person],
|
|
"PrimitiveArrays.date must be of type 'date[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optBool = [person],
|
|
"PrimitiveArrays.optBool must be of type 'boolean?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optInt = [person],
|
|
"PrimitiveArrays.optInt must be of type 'number?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optFloat = [person],
|
|
"PrimitiveArrays.optFloat must be of type 'number?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optDouble = [person],
|
|
"PrimitiveArrays.optDouble must be of type 'number?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optString = [person],
|
|
"PrimitiveArrays.optString must be of type 'string?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optData = [person],
|
|
"PrimitiveArrays.optData must be of type 'binary?[]', got 'object' ([PersonObject{");
|
|
TestCase.assertThrowsContaining(() => prim.optDate = [person],
|
|
"PrimitiveArrays.optDate must be of type 'date?[]', got 'object' ([PersonObject{");
|
|
|
|
function testAssign(name, value) {
|
|
prim[name] = [value];
|
|
TestCase.assertSimilar(prim[name].type, prim[name][0], value, undefined, 1);
|
|
}
|
|
|
|
testAssign('bool', true);
|
|
testAssign('int', 1);
|
|
testAssign('float', 1.1);
|
|
testAssign('double', 1.1);
|
|
testAssign('string', 'a');
|
|
testAssign('data', DATA1);
|
|
testAssign('date', DATE1);
|
|
|
|
function testAssignNull(name, expected) {
|
|
TestCase.assertThrowsContaining(() => prim[name] = [null],
|
|
`PrimitiveArrays.${name} must be of type '${expected}[]', got 'object' ([null])`,
|
|
undefined, 1);
|
|
TestCase.assertEqual(prim[name].length, 1,
|
|
"List should not have been cleared by invalid assignment", 1);
|
|
}
|
|
|
|
testAssignNull('bool', 'boolean');
|
|
testAssignNull('int', 'number');
|
|
testAssignNull('float', 'number');
|
|
testAssignNull('double', 'number');
|
|
testAssignNull('string', 'string');
|
|
testAssignNull('data', 'binary');
|
|
testAssignNull('date', 'date');
|
|
|
|
testAssign('optBool', true);
|
|
testAssign('optInt', 1);
|
|
testAssign('optFloat', 1.1);
|
|
testAssign('optDouble', 1.1);
|
|
testAssign('optString', 'a');
|
|
testAssign('optData', DATA1);
|
|
testAssign('optDate', DATE1);
|
|
|
|
testAssign('optBool', null);
|
|
testAssign('optInt', null);
|
|
testAssign('optFloat', null);
|
|
testAssign('optDouble', null);
|
|
testAssign('optString', null);
|
|
testAssign('optData', null);
|
|
testAssign('optDate', null);
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => obj.arrayCol = [],
|
|
"Cannot modify managed objects outside of a write transaction.");
|
|
TestCase.assertThrowsContaining(() => prim.bool = [],
|
|
"Cannot modify managed objects outside of a write transaction.");
|
|
},
|
|
|
|
testListEnumerate: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let obj;
|
|
|
|
realm.write(() => {
|
|
obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [],
|
|
});
|
|
});
|
|
|
|
for (const index in obj.arrayCol) {
|
|
TestCase.assertTrue(false, "No objects should have been enumerated: " + index);
|
|
}
|
|
|
|
realm.write(() => {
|
|
obj.arrayCol = [{doubleCol: 0}, {doubleCol: 1}];
|
|
});
|
|
TestCase.assertEqual(obj.arrayCol.length, 2);
|
|
|
|
let count = 0;
|
|
let keys = Object.keys(obj.arrayCol);
|
|
for (const index in obj.arrayCol) {
|
|
TestCase.assertEqual(count++, +index);
|
|
TestCase.assertEqual(keys[index], index);
|
|
}
|
|
|
|
TestCase.assertEqual(count, 2);
|
|
TestCase.assertEqual(keys.length, 2);
|
|
},
|
|
|
|
testListPush: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
TestCase.assertEqual(array.length, 1);
|
|
|
|
TestCase.assertEqual(array.push({doubleCol: 4}), 2);
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(array[1].doubleCol, 4);
|
|
|
|
TestCase.assertEqual(array.push(obj.objectCol, obj.objectCol1), 4);
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertEqual(array[2].doubleCol, 1);
|
|
TestCase.assertEqual(array[3].doubleCol, 2);
|
|
|
|
TestCase.assertEqual(array.push(), 4);
|
|
TestCase.assertEqual(array.length, 4);
|
|
});
|
|
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertThrowsContaining(() => {
|
|
array.push([1]);
|
|
}, "Cannot modify managed objects outside of a write transaction.");
|
|
},
|
|
|
|
testListPop: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
TestCase.assertEqual(array.pop().doubleCol, 4);
|
|
TestCase.assertEqual(array.pop().doubleCol, 3);
|
|
TestCase.assertEqual(array.length, 0);
|
|
|
|
TestCase.assertEqual(array.pop(), undefined);
|
|
|
|
TestCase.assertThrowsContaining(() => array.pop(1), 'Invalid argument');
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => array.pop(),
|
|
"Cannot modify managed objects outside of a write transaction.");
|
|
},
|
|
|
|
testListUnshift: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
TestCase.assertEqual(array.length, 1);
|
|
|
|
TestCase.assertEqual(array.unshift({doubleCol: 5}), 2);
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(array[0].doubleCol, 5);
|
|
|
|
TestCase.assertEqual(array.unshift(obj.objectCol, obj.objectCol1), 4);
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
|
TestCase.assertEqual(array[1].doubleCol, 2);
|
|
|
|
TestCase.assertEqual(array.unshift(), 4);
|
|
TestCase.assertEqual(array.length, 4);
|
|
});
|
|
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertThrowsContaining(() => array.unshift({doubleCol: 1}),
|
|
'Cannot modify managed objects outside of a write transaction.');
|
|
},
|
|
|
|
testListShift: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
TestCase.assertEqual(array.shift().doubleCol, 3);
|
|
TestCase.assertEqual(array.shift().doubleCol, 4);
|
|
TestCase.assertEqual(array.length, 0);
|
|
|
|
TestCase.assertEqual(array.shift(), undefined);
|
|
|
|
TestCase.assertThrowsContaining(() => array.shift(1), 'Invalid argument');
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => {
|
|
array.shift();
|
|
}, "Cannot modify managed objects outside of a write transaction.");
|
|
},
|
|
|
|
testListSplice: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
let removed;
|
|
|
|
removed = array.splice(0, 0, obj.objectCol, obj.objectCol1);
|
|
TestCase.assertEqual(removed.length, 0);
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
|
TestCase.assertEqual(array[1].doubleCol, 2);
|
|
|
|
removed = array.splice(2, 2, {doubleCol: 5}, {doubleCol: 6});
|
|
TestCase.assertEqual(removed.length, 2);
|
|
TestCase.assertEqual(removed[0].doubleCol, 3);
|
|
TestCase.assertEqual(removed[1].doubleCol, 4);
|
|
TestCase.assertEqual(array.length, 4);
|
|
TestCase.assertEqual(array[2].doubleCol, 5);
|
|
TestCase.assertEqual(array[3].doubleCol, 6);
|
|
|
|
removed = array.splice(2, 2);
|
|
TestCase.assertEqual(removed.length, 2);
|
|
TestCase.assertEqual(removed[0].doubleCol, 5);
|
|
TestCase.assertEqual(removed[1].doubleCol, 6);
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
|
TestCase.assertEqual(array[1].doubleCol, 2);
|
|
|
|
removed = array.splice(-1, 1);
|
|
TestCase.assertEqual(removed.length, 1);
|
|
TestCase.assertEqual(removed[0].doubleCol, 2);
|
|
TestCase.assertEqual(array.length, 1);
|
|
TestCase.assertEqual(array[0].doubleCol, 1);
|
|
|
|
removed = array.splice(0, 2);
|
|
TestCase.assertEqual(removed.length, 1);
|
|
TestCase.assertEqual(removed[0].doubleCol, 1);
|
|
TestCase.assertEqual(array.length, 0);
|
|
|
|
removed = array.splice('0', '0', obj.objectCol);
|
|
TestCase.assertEqual(removed.length, 0);
|
|
TestCase.assertEqual(array.length, 1);
|
|
|
|
removed = array.splice(1);
|
|
TestCase.assertEqual(removed.length, 0);
|
|
TestCase.assertEqual(array.length, 1);
|
|
|
|
removed = array.splice(0);
|
|
TestCase.assertEqual(removed.length, 1);
|
|
TestCase.assertEqual(array.length, 0);
|
|
|
|
TestCase.assertThrowsContaining(() => {
|
|
array.splice('cat', 1);
|
|
}, "Value 'cat' not convertible to a number");
|
|
|
|
TestCase.assertThrowsContaining(() => {
|
|
array.splice(0, 0, 0);
|
|
}, "JS value must be of type 'object', got (0)");
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => {
|
|
array.splice(0, 0, {doubleCol: 1});
|
|
}, "Cannot modify managed objects outside of a write transaction");
|
|
},
|
|
|
|
testListDeletions: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let object;
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
object = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
|
|
array = object.arrayCol;
|
|
});
|
|
|
|
try {
|
|
realm.write(() => {
|
|
realm.delete(array[0]);
|
|
TestCase.assertEqual(array.length, 1);
|
|
TestCase.assertEqual(array[0].doubleCol, 4);
|
|
|
|
// This should cancel the transaction and cause the list to be reset.
|
|
throw new Error('Transaction FAIL');
|
|
});
|
|
} catch (e) {}
|
|
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(array[0].doubleCol, 3);
|
|
|
|
realm.write(() => {
|
|
realm.delete(object);
|
|
});
|
|
|
|
TestCase.assertThrowsContaining(() => array[0], 'invalidated');
|
|
},
|
|
|
|
testLiveUpdatingResults: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let objects = realm.objects('TestObject');
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', {
|
|
objectCol: {doubleCol: 1},
|
|
objectCol1: {doubleCol: 2},
|
|
arrayCol: [{doubleCol: 3}, {doubleCol: 4}],
|
|
});
|
|
|
|
array = obj.arrayCol;
|
|
});
|
|
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(objects.length, 4);
|
|
|
|
try {
|
|
realm.write(() => {
|
|
array.push({doubleCol: 5});
|
|
TestCase.assertEqual(objects.length, 5);
|
|
|
|
array.unshift({doubleCol: 2});
|
|
TestCase.assertEqual(objects.length, 6);
|
|
|
|
array.splice(0, 0, {doubleCol: 1});
|
|
TestCase.assertEqual(objects.length, 7);
|
|
|
|
array.push(objects[0], objects[1]);
|
|
TestCase.assertEqual(objects.length, 7);
|
|
|
|
// This should cancel the transaction and cause the list and results to be reset.
|
|
throw new Error('Transaction FAIL');
|
|
});
|
|
} catch (e) {}
|
|
|
|
TestCase.assertEqual(array.length, 2);
|
|
TestCase.assertEqual(objects.length, 4);
|
|
},
|
|
|
|
testListSnapshot: function() {
|
|
const realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]});
|
|
let objects = realm.objects('TestObject');
|
|
let array;
|
|
|
|
realm.write(() => {
|
|
let obj = realm.create('LinkTypesObject', [[1], [2], [[3], [4]], [[5], [6]]]);
|
|
array = obj.arrayCol;
|
|
});
|
|
|
|
let objectsCopy = objects.snapshot();
|
|
let arrayCopy = array.snapshot();
|
|
|
|
TestCase.assertEqual(objectsCopy.length, 6);
|
|
TestCase.assertEqual(arrayCopy.length, 2);
|
|
|
|
realm.write(() => {
|
|
array.push([5]);
|
|
TestCase.assertEqual(objectsCopy.length, 6);
|
|
TestCase.assertEqual(arrayCopy.length, 2);
|
|
|
|
TestCase.assertEqual(objectsCopy.snapshot().length, 6);
|
|
TestCase.assertEqual(arrayCopy.snapshot().length, 2);
|
|
|
|
TestCase.assertEqual(objects.snapshot().length, 7);
|
|
TestCase.assertEqual(array.snapshot().length, 3);
|
|
|
|
realm.delete(array[0]);
|
|
TestCase.assertEqual(objectsCopy.length, 6);
|
|
TestCase.assertEqual(arrayCopy.length, 2);
|
|
TestCase.assertEqual(arrayCopy[0], null);
|
|
|
|
realm.deleteAll();
|
|
TestCase.assertEqual(objectsCopy.length, 6);
|
|
TestCase.assertEqual(arrayCopy.length, 2);
|
|
TestCase.assertEqual(arrayCopy[1], null);
|
|
});
|
|
},
|
|
|
|
testListFiltered: function() {
|
|
const realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
|
|
let list;
|
|
|
|
realm.write(() => {
|
|
let object = realm.create('PersonList', {list: [
|
|
{name: 'Ari', age: 10},
|
|
{name: 'Tim', age: 11},
|
|
{name: 'Bjarne', age: 12},
|
|
{name: 'Alex', age: 12, married: true}
|
|
]});
|
|
realm.create('PersonObject', {name: 'NotInList', age: 10});
|
|
|
|
list = object.list;
|
|
});
|
|
|
|
TestCase.assertEqual(list.filtered("truepredicate").length, 4);
|
|
TestCase.assertEqual(list.filtered('age = 11')[0].name, 'Tim');
|
|
TestCase.assertEqual(list.filtered('age = 12').length, 2);
|
|
TestCase.assertEqual(list.filtered('age > 10 && age < 13').length, 3);
|
|
TestCase.assertEqual(list.filtered('age > 10').filtered('age < 13').length, 3);
|
|
},
|
|
|
|
testListSorted: function() {
|
|
const schema = [
|
|
{name: 'Target', properties: {value: 'int'}},
|
|
{name: 'Mid', properties: {value: 'int', link: 'Target'}},
|
|
{name: 'List', properties: {list: {type: 'list', objectType: 'Mid'}}},
|
|
schemas.PrimitiveArrays
|
|
];
|
|
const realm = new Realm({schema: schema});
|
|
|
|
let list, prim;
|
|
realm.write(() => {
|
|
list = realm.create('List', {list: [
|
|
{value: 3, link: {value: 1}},
|
|
{value: 1, link: {value: 3}},
|
|
{value: 2, link: {value: 2}},
|
|
]}).list;
|
|
realm.create('List', {list: [
|
|
{value: 4, link: {value: 4}},
|
|
]});
|
|
prim = realm.create('PrimitiveArrays', {
|
|
bool: [true, false],
|
|
int: [3, 1, 2],
|
|
float: [3, 1, 2],
|
|
double: [3, 1, 2],
|
|
string: ['c', 'a', 'b'],
|
|
data: [DATA3, DATA1, DATA2],
|
|
date: [DATE3, DATE1, DATE2],
|
|
optBool: [true, false, null],
|
|
optInt: [3, 1, 2, null],
|
|
optFloat: [3, 1, 2, null],
|
|
optDouble: [3, 1, 2, null],
|
|
optString: ['c', 'a', 'b', null],
|
|
optData: [DATA3, DATA1, DATA2, null],
|
|
optDate: [DATE3, DATE1, DATE2, null],
|
|
});
|
|
});
|
|
|
|
const values = (results) => results.map((o) => o.value);
|
|
|
|
// TestCase.assertThrowsContaining(() => list.sorted());
|
|
TestCase.assertThrowsContaining(() => list.sorted('nonexistent property'),
|
|
"Cannot sort on key path 'nonexistent property': property 'Mid.nonexistent property' does not exist.");
|
|
TestCase.assertThrowsContaining(() => list.sorted('link'),
|
|
"Cannot sort on key path 'link': property 'Mid.link' of type 'object' cannot be the final property in the key path.");
|
|
|
|
TestCase.assertArraysEqual(values(list.sorted([])), [3, 1, 2]);
|
|
|
|
TestCase.assertArraysEqual(values(list.sorted('value')), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(values(list.sorted('value', false)), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(values(list.sorted('value', true)), [3, 2, 1]);
|
|
TestCase.assertArraysEqual(values(list.sorted(['value'])), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(values(list.sorted([['value', false]])), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(values(list.sorted([['value', true]])), [3, 2, 1]);
|
|
|
|
TestCase.assertArraysEqual(values(list.sorted('link.value')), [3, 2, 1]);
|
|
TestCase.assertArraysEqual(values(list.sorted('link.value', false)), [3, 2, 1]);
|
|
TestCase.assertArraysEqual(values(list.sorted('link.value', true)), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(values(list.sorted(['link.value'])), [3, 2, 1]);
|
|
TestCase.assertArraysEqual(values(list.sorted([['link.value', false]])), [3, 2, 1]);
|
|
TestCase.assertArraysEqual(values(list.sorted([['link.value', true]])), [1, 2, 3]);
|
|
|
|
TestCase.assertThrowsContaining(() => prim.int.sorted('value', true),
|
|
"Cannot sort on key path 'value': arrays of 'int' can only be sorted on 'self'");
|
|
TestCase.assertThrowsContaining(() => prim.int.sorted('!ARRAY_VALUE', true),
|
|
"Cannot sort on key path '!ARRAY_VALUE': arrays of 'int' can only be sorted on 'self'");
|
|
|
|
TestCase.assertArraysEqual(prim.int.sorted([]), [3, 1, 2]);
|
|
TestCase.assertArraysEqual(prim.int.sorted(), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.int.sorted(false), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.int.sorted(true), [3, 2, 1]);
|
|
|
|
TestCase.assertArraysEqual(prim.optInt.sorted([]), [3, 1, 2, null]);
|
|
TestCase.assertArraysEqual(prim.optInt.sorted(), [null, 1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.optInt.sorted(false), [null, 1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.optInt.sorted(true), [3, 2, 1, null]);
|
|
|
|
TestCase.assertArraysEqual(prim.bool.sorted(), [false, true]);
|
|
TestCase.assertArraysEqual(prim.float.sorted(), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.double.sorted(), [1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.string.sorted(), ['a', 'b', 'c']);
|
|
TestCase.assertArraysEqual(prim.data.sorted(), [DATA1, DATA2, DATA3]);
|
|
TestCase.assertArraysEqual(prim.date.sorted(), [DATE1, DATE2, DATE3]);
|
|
TestCase.assertArraysEqual(prim.optBool.sorted(), [null, false, true]);
|
|
TestCase.assertArraysEqual(prim.optFloat.sorted(), [null, 1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.optDouble.sorted(), [null, 1, 2, 3]);
|
|
TestCase.assertArraysEqual(prim.optString.sorted(), [null, 'a', 'b', 'c']);
|
|
TestCase.assertArraysEqual(prim.optData.sorted(), [null, DATA1, DATA2, DATA3]);
|
|
TestCase.assertArraysEqual(prim.optDate.sorted(), [null, DATE1, DATE2, DATE3]);
|
|
},
|
|
|
|
testArrayMethods: function() {
|
|
const realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList, schemas.PrimitiveArrays]});
|
|
let object, prim;
|
|
|
|
realm.write(() => {
|
|
object = realm.create('PersonList', {list: [
|
|
{name: 'Ari', age: 10},
|
|
{name: 'Tim', age: 11},
|
|
{name: 'Bjarne', age: 12},
|
|
]});
|
|
prim = realm.create('PrimitiveArrays', {int: [10, 11, 12]});
|
|
});
|
|
|
|
for (const list of [object.list, realm.objects('PersonObject')]) {
|
|
TestCase.assertEqual(list.slice().length, 3);
|
|
TestCase.assertEqual(list.slice(-1).length, 1);
|
|
TestCase.assertEqual(list.slice(-1)[0].age, 12);
|
|
TestCase.assertEqual(list.slice(1, 3).length, 2);
|
|
TestCase.assertEqual(list.slice(1, 3)[1].age, 12);
|
|
|
|
// A Node 6 regression in v8 causes an error when converting our objects to strings:
|
|
// TypeError: Cannot convert a Symbol value to a string
|
|
if (!TestCase.isNode6()) {
|
|
TestCase.assertEqual(list.join(' '), 'Ari Tim Bjarne');
|
|
}
|
|
|
|
let count = 0;
|
|
list.forEach((p, i) => {
|
|
TestCase.assertEqual(p.name, list[i].name);
|
|
count++;
|
|
});
|
|
TestCase.assertEqual(count, list.length);
|
|
|
|
TestCase.assertArraysEqual(list.map(p => p.age), [10, 11, 12]);
|
|
TestCase.assertTrue(list.some(p => p.age > 10));
|
|
TestCase.assertTrue(list.every(p => p.age > 0));
|
|
|
|
let person = list.find(p => p.name == 'Tim');
|
|
TestCase.assertEqual(person.name, 'Tim');
|
|
|
|
let index = list.findIndex(p => p.name == 'Tim');
|
|
TestCase.assertEqual(index, 1);
|
|
TestCase.assertEqual(list.indexOf(list[index]), index);
|
|
|
|
TestCase.assertEqual(list.reduce((n, p) => n + p.age, 0), 33);
|
|
TestCase.assertEqual(list.reduceRight((n, p) => n + p.age, 0), 33);
|
|
|
|
// eslint-disable-next-line no-undef
|
|
let iteratorMethodNames = ['entries', 'keys', 'values'];
|
|
|
|
iteratorMethodNames.push(Symbol.iterator);
|
|
|
|
iteratorMethodNames.forEach(methodName => {
|
|
let iterator = list[methodName]();
|
|
let count = 0;
|
|
let result;
|
|
|
|
// This iterator should itself be iterable.
|
|
// TestCase.assertEqual(iterator[iteratorSymbol](), iterator);
|
|
TestCase.assertEqual(iterator[Symbol.iterator](), iterator);
|
|
|
|
while ((result = iterator.next()) && !result.done) {
|
|
let value = result.value;
|
|
|
|
switch (methodName) {
|
|
case 'entries':
|
|
TestCase.assertEqual(value.length, 2);
|
|
TestCase.assertEqual(value[0], count);
|
|
TestCase.assertEqual(value[1].name, list[count].name);
|
|
break;
|
|
case 'keys':
|
|
TestCase.assertEqual(value, count);
|
|
break;
|
|
default:
|
|
TestCase.assertEqual(value.name, list[count].name);
|
|
break;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
TestCase.assertEqual(result.done, true);
|
|
TestCase.assertEqual(result.value, undefined);
|
|
TestCase.assertEqual(count, list.length);
|
|
});
|
|
}
|
|
|
|
const list = prim.int;
|
|
TestCase.assertEqual(list.slice().length, 3);
|
|
TestCase.assertEqual(list.slice(-1).length, 1);
|
|
TestCase.assertEqual(list.slice(-1)[0], 12);
|
|
TestCase.assertEqual(list.slice(1, 3).length, 2);
|
|
TestCase.assertEqual(list.slice(1, 3)[1], 12);
|
|
|
|
TestCase.assertEqual(list.join(' '), '10 11 12');
|
|
|
|
let count = 0;
|
|
list.forEach((v, i) => {
|
|
TestCase.assertEqual(v, i + 10);
|
|
count++;
|
|
});
|
|
TestCase.assertEqual(count, list.length);
|
|
|
|
TestCase.assertArraysEqual(list.map(p => p + 1), [11, 12, 13]);
|
|
TestCase.assertTrue(list.some(p => p > 10));
|
|
TestCase.assertTrue(list.every(p => p > 0));
|
|
|
|
let value = list.find(p => p == 11);
|
|
TestCase.assertEqual(value, 11)
|
|
|
|
let index = list.findIndex(p => p == 11);
|
|
TestCase.assertEqual(index, 1);
|
|
TestCase.assertEqual(list.indexOf(list[index]), index);
|
|
|
|
TestCase.assertEqual(list.reduce((n, p) => n + p, 0), 33);
|
|
TestCase.assertEqual(list.reduceRight((n, p) => n + p, 0), 33);
|
|
|
|
// eslint-disable-next-line no-undef
|
|
let iteratorMethodNames = ['entries', 'keys', 'values'];
|
|
|
|
iteratorMethodNames.push(Symbol.iterator);
|
|
|
|
iteratorMethodNames.forEach(methodName => {
|
|
let iterator = list[methodName]();
|
|
let count = 0;
|
|
let result;
|
|
|
|
// This iterator should itself be iterable.
|
|
// TestCase.assertEqual(iterator[iteratorSymbol](), iterator);
|
|
TestCase.assertEqual(iterator[Symbol.iterator](), iterator);
|
|
|
|
while ((result = iterator.next()) && !result.done) {
|
|
let value = result.value;
|
|
|
|
switch (methodName) {
|
|
case 'entries':
|
|
TestCase.assertEqual(value.length, 2);
|
|
TestCase.assertEqual(value[0], count);
|
|
TestCase.assertEqual(value[1], list[count]);
|
|
break;
|
|
case 'keys':
|
|
TestCase.assertEqual(value, count);
|
|
break;
|
|
default:
|
|
TestCase.assertEqual(value.name, list[count].name);
|
|
break;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
TestCase.assertEqual(result.done, true);
|
|
TestCase.assertEqual(result.value, undefined);
|
|
TestCase.assertEqual(count, list.length);
|
|
});
|
|
},
|
|
|
|
testIsValid: function() {
|
|
const realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
|
|
let object;
|
|
let list;
|
|
realm.write(() => {
|
|
object = realm.create('PersonList', {list: [
|
|
{name: 'Ari', age: 10},
|
|
{name: 'Tim', age: 11},
|
|
{name: 'Bjarne', age: 12},
|
|
]});
|
|
list = object.list;
|
|
TestCase.assertEqual(list.isValid(), true);
|
|
realm.delete(object);
|
|
});
|
|
|
|
TestCase.assertEqual(list.isValid(), false);
|
|
TestCase.assertThrowsContaining(() => list.length, 'invalidated');
|
|
},
|
|
};
|