Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for TS create declarations when updating (v6) #3271

Merged
merged 9 commits into from
Oct 2, 2020
250 changes: 228 additions & 22 deletions integration-tests/tests/src/objects.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,239 @@
import { expect } from "chai";

import { IPerson, PersonSchema } from "./schemas/person-and-dogs";
import {
IPerson as IPersonWithId,
Person as PersonWithId,
PersonSchema as PersonSchemaWithId
} from "./schemas/person-and-dog-with-primary-ids";
import { IPerson, Person, PersonSchema } from "./schemas/person-and-dogs";

describe("Realm objects", () => {
it("can be created", () => {
const realm = new Realm({ schema: [PersonSchema] });
let john: IPerson;
realm.write(() => {
john = realm.create<IPerson>("Person", {
name: "John Doe",
age: 42
});
});
// Expect John to be the one and only result
const persons = realm.objects("Person");
expect(persons.length).equals(1);
const [firstPerson] = persons;
expect(firstPerson).deep.equals(john);
describe("Interface & object literal", () => {
it("can be created", () => {
const realm = new Realm({ schema: [PersonSchema] });
let john: IPerson;

realm.write(() => {
john = realm.create<IPerson>(PersonSchema.name, {
name: "John Doe",
age: 42
});
});

// Expect John to be the one and only result
const persons = realm.objects(PersonSchema.name);
expect(persons.length).equals(1);
const [firstPerson] = persons;
expect(firstPerson).deep.equals(john);
});

it("can have it's properties read", () => {
const realm = new Realm({ schema: [PersonSchema] });
let john: IPerson;

realm.write(() => {
john = realm.create<IPerson>(PersonSchema.name, {
name: "John Doe",
age: 42
});
});

expect(john.name).equals("John Doe");
expect(john.age).equals(42);
});

it("can be fetched with objectForPrimaryKey", () => {
const realm = new Realm({ schema: [PersonSchemaWithId] });
const _id = "0e19bcb8-c77a-44e5-9713-d6a59702869f";

realm.write(() => {
realm.create<PersonWithId>(PersonSchemaWithId.name, {
_id,
name: "John Doe",
age: 42
});
});

const john = realm.objectForPrimaryKey<IPersonWithId>(
PersonSchemaWithId.name,
_id
);

expect(john).instanceOf(Realm.Object);
expect(john._id).equals(_id);
expect(john.name).equals("John Doe");
expect(john.age).equals(42);
});

it("can be updated", () => {
const realm = new Realm({ schema: [PersonSchemaWithId] });
let john: IPersonWithId;
const _id = "8ef4d2e2-a8be-468d-995d-36068d15b520";

realm.write(() => {
john = realm.create<IPersonWithId>(PersonSchemaWithId.name, {
_id,
name: "John Doe",
age: 42
});
});

expect(john.name).equals("John Doe");
expect(john.age).equals(42);

realm.write(() => {
realm.create<IPersonWithId>(
PersonSchemaWithId.name,
{ _id, age: 43 },
Realm.UpdateMode.All
);
});

expect(john.name).equals("John Doe");
expect(john.age).equals(43);

const update: Partial<IPersonWithId> = {
_id,
name: "Mr. John Doe"
};

realm.write(() => {
realm.create<IPersonWithId>(
PersonSchemaWithId.name,
update,
Realm.UpdateMode.Modified
);
});

expect(john.name).equals("Mr. John Doe");
expect(john.age).equals(43);

expect(() =>
realm.write(() => {
realm.create<IPersonWithId>(
PersonSchemaWithId.name,
{ _id, name: "John Doe", age: 42 },
Realm.UpdateMode.Never
);
})
).throws(
`Attempting to create an object of type '${
PersonSchemaWithId.name
}' with an existing primary key value ''${_id}''.`
);

// Excpect only one instance of 'PersonSchemaWithId' in db after all updates
const persons = realm.objects(PersonSchemaWithId.name);
expect(persons.length).equals(1);
});
});

it("can have it's properties read", () => {
const realm = new Realm({ schema: [PersonSchema] });
realm.write(() => {
const john = realm.create<IPerson>("Person", {
name: "John Doe",
age: 42
describe("Class Model", () => {
it("can be created", () => {
const realm = new Realm({ schema: [Person] });
let john: Person;

realm.write(() => {
john = realm.create(Person, {
name: "John Doe",
age: 42
});
});
// Expect John to be the one and only result
const persons = realm.objects(Person);
expect(persons.length).equals(1);
const [firstPerson] = persons;
expect(firstPerson).deep.equals(john);
expect(firstPerson).instanceOf(Person);
});

it("can have it's properties read", () => {
const realm = new Realm({ schema: [Person] });
realm.write(() => {
const john = realm.create(Person, {
name: "John Doe",
age: 42
});
expect(john.name).equals("John Doe");
expect(john.age).equals(42);
});
});

it("can be fetched with objectForPrimaryKey", () => {
const realm = new Realm({ schema: [PersonWithId] });
const _id = "1d84d60b-8c64-4531-bfdc-87cdd9e029c3";

realm.write(() => {
realm.create(PersonWithId, {
_id,
name: "John Doe",
age: 42
});
});

const john = realm.objectForPrimaryKey(PersonWithId, _id);

expect(john).instanceOf(PersonWithId);
expect(john._id).equals(_id);
expect(john.name).equals("John Doe");
expect(john.age).equals(42);
});

it("can be updated", () => {
const realm = new Realm({ schema: [PersonWithId] });
let john: PersonWithId;
const _id = "e4762cd3-b92f-47ae-857a-26eba201e7db";

realm.write(() => {
john = realm.create(PersonWithId, {
_id,
name: "John Doe",
age: 42
});
});

expect(john.name).equals("John Doe");
expect(john.age).equals(42);

realm.write(() => {
realm.create(
PersonWithId,
{ _id, age: 43 },
Realm.UpdateMode.All
);
});

expect(john.name).equals("John Doe");
expect(john.age).equals(43);

const update: Partial<PersonWithId> = {
_id,
name: "Mr. John Doe"
};

realm.write(() => {
realm.create(PersonWithId, update, Realm.UpdateMode.Modified);
});

expect(john.name).equals("Mr. John Doe");
expect(john.age).equals(43);

expect(() =>
realm.write(() => {
realm.create(
PersonWithId,
{ _id, name: "John Doe", age: 42 },
Realm.UpdateMode.Never
);
})
).throws(
`Attempting to create an object of type '${
PersonWithId.schema.name
}' with an existing primary key value ''${_id}''.`
);

// Excpect only one instance of 'PersonWithId' in db after all updates
const persons = realm.objects(PersonWithId);
expect(persons.length).equals(1);
});
});
});
8 changes: 5 additions & 3 deletions integration-tests/tests/src/serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,9 @@ describe("JSON serialization", () => {
});

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

Expand Down Expand Up @@ -291,7 +292,8 @@ describe("JSON serialization", () => {

it("throws correct error on serialization", () => {
expect(() => JSON.stringify(persons)).throws(
"Converting circular structure to JSON"
TypeError,
/circular|cyclic/i
);
});

Expand Down
38 changes: 20 additions & 18 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -938,38 +938,40 @@ declare class Realm {
/**
* @param {string} type
* @param {T} properties
* @param {boolean} update?
* @param {Realm.UpdateMode} mode? If not provided, `Realm.UpdateMode.Never` is used.
* @returns T & Realm.Object
*
* @deprecated, to be removed in future versions. Use `create(type, properties, UpdateMode)` instead.
*/
create<T>(type: string, properties: RealmInsertionModel<T>, update?: boolean): T & Realm.Object
create<T>(type: string, properties: RealmInsertionModel<T>, mode?: Realm.UpdateMode.Never): T & Realm.Object;
create<T>(type: string, properties: Partial<T> | Partial<RealmInsertionModel<T>>, mode: Realm.UpdateMode.All | Realm.UpdateMode.Modified): T & Realm.Object;

/**
* @param {Class} type
* @param {string} type
* @param {T} properties
* @param {boolean} update?
* @returns T
* @returns T & Realm.Object
*
* @deprecated, to be removed in future versions. Use `create(type, properties, UpdateMode)` instead.
*/
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: RealmInsertionModel<T>, update?: boolean): T
create<T>(type: string, properties: RealmInsertionModel<T>, update: boolean): T & Realm.Object;

/**
* @param {string} type
* @param {Class} type
* @param {T} properties
* @param {Realm.UpdateMode} mode? If not provided, `Realm.UpdateMode.Never` is used.
* @returns T & Realm.Object
* @returns T
*/
create<T>(type: string, properties: RealmInsertionModel<T>, mode?: Realm.UpdateMode): T & Realm.Object
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: RealmInsertionModel<T>, mode?: Realm.UpdateMode.Never): T;
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: Partial<T> | Partial<RealmInsertionModel<T>>, mode: Realm.UpdateMode.All | Realm.UpdateMode.Modified): T;

/**
/**
* @param {Class} type
* @param {T} properties
* @param {Realm.UpdateMode} mode? If not provided, `Realm.UpdateMode.Never` is used.
* @param {boolean} update?
* @returns T
*
* @deprecated, to be removed in future versions. Use `create(type, properties, UpdateMode)` instead.
*/
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: RealmInsertionModel<T>, mode?: Realm.UpdateMode): T
create<T extends Realm.Object>(type: {new(...arg: any[]): T; }, properties: RealmInsertionModel<T>, update: boolean): T

/**
* @param {Realm.Object|Realm.Object[]|Realm.List<any>|Realm.Results<any>|any} object
Expand All @@ -988,18 +990,18 @@ declare class Realm {
deleteAll(): void;

/**
* @param {string|Realm.ObjectType|Function} type
* @param {string} type
* @param {number|string} key
* @returns {T | undefined}
*/
objectForPrimaryKey<T>(type: string | Realm.ObjectType | Function, key: number | string): T & Realm.Object | undefined;
objectForPrimaryKey<T>(type: string, key: number | string): (T & Realm.Object) | undefined;

/**
* @param {string|Realm.ObjectType|Function} type
* @param {string} id
* @param {Class} type
* @param {number|string} key
* @returns {T | undefined}
*/
objectForPrimaryKey<T>(type: string | Realm.ObjectType | Function, id: string): T & Realm.Object | undefined;
objectForPrimaryKey<T extends Realm.Object>(type: {new(...arg: any[]): T; }, key: number | string): T | undefined;

/**
* @param {string} type
Expand Down