Skip to content

Commit

Permalink
Use the primaryKey as reference-id when possible. Added tests for Rea…
Browse files Browse the repository at this point in the history
…lm.Objects with primary keys. (#3053)
  • Loading branch information
steffenagger committed Aug 12, 2020
1 parent 4c39b07 commit f904701
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2019 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.
//
////////////////////////////////////////////////////////////////////////////

import * as Realm from "realm";
import { ObjectId } from 'bson'

export interface IPerson {
_id: ObjectId;
name: string;
age: number;
friends: Realm.List<IPerson>;
dogs: Realm.Collection<IDog>;
}

export const PersonSchema: Realm.ObjectSchema = {
name: "Person",
primaryKey: "_id",
properties: {
_id: "objectId",
age: "int",
name: "string",
friends: "Person[]"
}
};

export class Person extends Realm.Object {
_id: ObjectId;
name: string;
age: number;
friends: Realm.List<Person>;
dogs: Realm.Collection<Dog>;

static schema: Realm.ObjectSchema = PersonSchema;
}

export interface IDog {
_id: ObjectId;
name: string;
age: number;
owner: IPerson;
}

export const DogSchema: Realm.ObjectSchema = {
name: "Dog",
primaryKey: "_id",
properties: {
_id: "objectId",
age: "int",
name: "string",
owner: "Person"
}
};

export class Dog extends Realm.Object {
_id: ObjectId;
name: string;
age: number;
owner: Person;

static schema: Realm.ObjectSchema = DogSchema;
}
175 changes: 139 additions & 36 deletions integration-tests/tests/src/serialization.ts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
import { expect } from "chai";

import { IPerson, PersonSchema, DogSchema, Person, Dog } from "./schemas/person-and-dogs";
import {
IPerson as IPersonWithId,
PersonSchema as PersonSchemaWithId,
DogSchema as DogSchemaWithId,
Person as PersonWithId,
Dog as DogWithId
} from "./schemas/person-and-dog-with-object-ids";
import * as circularCollectionResult from "./structures/circular-collection-result.json"
import * as circularCollectionResultWithIds from "./structures/circular-collection-result-with-object-ids.json"
import { ObjectId } from 'bson'

type testSetup = {
describe("JSON serialization (exposed properties)", () => {
it("JsonSerializationReplacer is exposed on the Realm constructor", () => {
expect(typeof Realm.JsonSerializationReplacer).equals('function');
expect(Realm.JsonSerializationReplacer.length).equals(2);
});
})

type TestSetup = {
name: string,
testData: () => { john: any, persons: Realm.Results<any> }
testData: () => {
realm: Realm,
predefinedStructure: any,
},
};

const testSetups: testSetup[] = [
const testSetups: TestSetup[] = [
{
name: "Object literal",
testData: () => {
const realm = new Realm({ schema: [PersonSchema, DogSchema] });

const realm = new Realm({ schema: [PersonSchema, DogSchema], inMemory: true });
console.log('path', realm.path)

realm.write(() => {
const john = realm.create<IPerson>(PersonSchema.name, {
name: "John Doe",
Expand All @@ -39,18 +59,16 @@ const testSetups: testSetup[] = [
tony.friends.push(jane);
});

const persons = realm.objects<IPerson>(PersonSchema.name);

return {
john: persons[0],
persons
realm,
predefinedStructure: circularCollectionResult,
};
},
},
{
name: "Class models",
testData: () => {
const realm = new Realm({ schema: [Person, Dog] });
const realm = new Realm({ schema: [Person, Dog], inMemory: true });

realm.write(() => {
const john = realm.create(Person, {
Expand All @@ -76,64 +94,149 @@ const testSetups: testSetup[] = [

tony.friends.push(jane);
});

return {
realm,
predefinedStructure: circularCollectionResult
};
}
},
{
name: "Object literal with primary ObjectId",
testData: () => {
const realm = new Realm({ schema: [PersonSchemaWithId, DogSchemaWithId], inMemory: true });

realm.write(() => {
const john = realm.create<IPersonWithId>(PersonSchemaWithId.name, {
_id: new ObjectId("5f086d00ddf69c48082eb63b"),
name: "John Doe",
age: 42,
});
const jane = realm.create<IPersonWithId>(PersonSchemaWithId.name, {
_id: new ObjectId("5f086d00ddf69c48082eb63d"),
name: "Jane Doe",
age: 40
});
const tony = realm.create<IPersonWithId>(PersonSchemaWithId.name, {
_id: new ObjectId("5f086d00ddf69c48082eb63f"),
name: "Tony Doe",
age: 35
});

// ensure circular references
john.friends.push(john);
john.friends.push(jane);
john.friends.push(tony);

jane.friends.push(tony);
jane.friends.push(john);

tony.friends.push(jane);
});

const persons = realm.objects(Person);

return {
john: persons[0],
persons
realm,
predefinedStructure: circularCollectionResultWithIds
};
},
},
{
name: "Class models with primary ObjectId",
testData: () => {
const realm = new Realm({ schema: [PersonWithId, DogWithId], inMemory: true });

realm.write(() => {
const john = realm.create(PersonWithId, {
_id: new ObjectId("5f086d00ddf69c48082eb63b"),
name: "John Doe",
age: 42
});
const jane = realm.create(PersonWithId, {
_id: new ObjectId("5f086d00ddf69c48082eb63d"),
name: "Jane Doe",
age: 40,
});
const tony = realm.create(PersonWithId, {
_id: new ObjectId("5f086d00ddf69c48082eb63f"),
name: "Tony Doe",
age: 35
});

// ensure circular references
john.friends.push(john);
john.friends.push(jane);
john.friends.push(tony);

jane.friends.push(tony);
jane.friends.push(john);

tony.friends.push(jane);
});

return {
realm,
predefinedStructure: circularCollectionResultWithIds
};
}
}
];

describe("JSON serialization", () => {

it("JsonSerializationReplacer is exposed on the Realm constructor", () => {
expect(typeof Realm.JsonSerializationReplacer).equal('function');
expect(Realm.JsonSerializationReplacer.length).equal(2);
let testSetup: TestSetup;
let realm: Realm | null;
let predefinedStructure: any;
let persons: Realm.Results<any>;

beforeEach(() => {
({ realm, predefinedStructure } = testSetup.testData());
persons = realm.objects(PersonSchema.name).sorted("age", true);
});

testSetups.forEach((testSetup) => {
afterEach(() => {
if (realm) {
realm.write(() => {
realm.deleteAll();
})
realm.close();
realm = null;
}
});

testSetups.forEach((ts) => {
// expose testSetup to predefined before/after hooks
testSetup = ts

describe(`Repeated test for "${testSetup.name}":`, () => {

describe("Realm.Object", () => {
let john: any;

beforeEach(() => {
john = testSetup.testData().john;
})

it("implements toJSON", () => {
expect(typeof john.toJSON).equals('function');
expect(typeof persons[0].toJSON).equals('function');
});

it("toJSON returns a circular structure", () => {
const serializable = john.toJSON();
const serializable = persons[0].toJSON();

expect(serializable.objectSchema).equals(undefined);
expect(serializable.friends).instanceOf(Array);
expect(serializable).equal(serializable.friends[0]);
expect(serializable).equals(serializable.friends[0]);
});

it("throws correct error on serialization", () => {
expect(() => JSON.stringify(john))
expect(() => JSON.stringify(persons[0]))
.throws(TypeError, /^Converting circular structure to JSON/);
});

it("serializes to expected output using Realm.JsonSerializationReplacer", () => {
expect(JSON.stringify(john, Realm.JsonSerializationReplacer))
.equals(JSON.stringify(circularCollectionResult[0]));
expect(JSON.stringify(persons[0], Realm.JsonSerializationReplacer))
.equals(JSON.stringify(predefinedStructure[0]));
})
});

describe("Realm.Results", () => {
let persons!: Realm.Results<any>;

beforeEach(() => {
persons = testSetup.testData().persons;
})


it("implements toJSON", () => {
expect(typeof persons.toJSON).equals('function');
});
Expand All @@ -143,7 +246,7 @@ describe("JSON serialization", () => {

expect(serializable).instanceOf(Array);
expect(serializable[0].friends).instanceOf(Array);
expect(serializable[0]).equal(serializable[0].friends[0]);
expect(serializable[0]).equals(serializable[0].friends[0]);
});

it("throws correct error on serialization", () => {
Expand All @@ -153,7 +256,7 @@ describe("JSON serialization", () => {

it("serializes to expected output using Realm.JsonSerializationReplacer", () => {
expect(JSON.stringify(persons, Realm.JsonSerializationReplacer))
.equal(JSON.stringify(circularCollectionResult));
.equals(JSON.stringify(predefinedStructure));
})
});
});
Expand Down
Loading

0 comments on commit f904701

Please sign in to comment.