Skip to content

Commit

Permalink
Make integration tests conform to new parser (#5216)
Browse files Browse the repository at this point in the history
  • Loading branch information
elle-j authored Jan 6, 2023
1 parent fb6d8ef commit ccc36e0
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 142 deletions.
2 changes: 1 addition & 1 deletion integration-tests/tests/src/tests/class-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe("Class models", () => {
}
expect(() => {
new Realm({ schema: [Person as any] });
}).throws("Expected 'properties' to be an object, got undefined");
}).throws("Expected 'properties' on 'Person' to be an object, got undefined");
});

it("fails if it doesn't extend Realm.Object", () => {
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/tests/src/tests/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("Dictionary", () => {
schema: [
{
name: "Item",
properties: { dict: "{}" },
properties: { dict: "mixed{}" },
},
{
name: "Person",
Expand Down Expand Up @@ -236,7 +236,7 @@ describe("Dictionary", () => {
schema: [
{
name: "Item",
properties: { dict: "{}" },
properties: { dict: "mixed{}" },
},
],
});
Expand Down
8 changes: 4 additions & 4 deletions integration-tests/tests/src/tests/dynamic-schema-updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe("realm._updateSchema", () => {
const MyClassSchema = this.realm.schema.find((s) => s.name === "MyClass");
expect(MyClassSchema).deep.equals({
name: "MyClass",
constructor: undefined,
ctor: undefined,
asymmetric: false,
embedded: false,
properties: {
Expand Down Expand Up @@ -86,7 +86,7 @@ describe("realm._updateSchema", () => {
const ModifiedDogSchema = this.realm.schema.find((s) => s.name === "Dog");
expect(ModifiedDogSchema).deep.equals({
name: "Dog",
constructor: undefined,
ctor: undefined,
asymmetric: false,
embedded: false,
properties: {
Expand Down Expand Up @@ -172,7 +172,7 @@ describe("realm._updateSchema", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(this.realm as any)._updateSchema();
});
}).to.throw("Expected 'schema' to be an array, got undefined");
}).to.throw("Expected 'realm schema' to be an array, got undefined");
});

it("throws if called with an unexpected type", function (this: RealmContext) {
Expand All @@ -181,6 +181,6 @@ describe("realm._updateSchema", () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(this.realm as any)._updateSchema("w00t");
});
}).to.throw("Expected 'schema' to be an array, got a string");
}).to.throw("Expected 'realm schema' to be an array, got a string");
});
});
51 changes: 23 additions & 28 deletions integration-tests/tests/src/tests/realm-constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe("Realm#constructor", () => {
it("fails when passed an object", () => {
expect(() => {
new RealmAsAny({ schema: {} });
}).throws("Expected 'schema' to be an array, got an object");
}).throws("Expected 'realm schema' to be an array, got an object");
});

it("fails when passed an array with non-objects", () => {
Expand All @@ -171,22 +171,29 @@ describe("Realm#constructor", () => {
it("fails when passed an array with empty object", () => {
expect(() => {
new RealmAsAny({ schema: [{}] });
}).throws("Expected 'name' to be a string, got undefined");
}).throws("Expected 'name' on object schema to be a string, got undefined");
});

it("fails when passed an array with an object without 'properties'", () => {
expect(() => {
new RealmAsAny({ schema: [{ name: "SomeObject" }] });
}).throws("Expected 'properties' to be an object, got undefined");
}).throws("Expected 'properties' on 'SomeObject' to be an object, got undefined");
});

it("fails when passed an array with an object without 'name'", () => {
expect(() => {
new RealmAsAny({ schema: [{ properties: {} }] });
}).throws("Expected 'name' to be a string, got undefined");
}).throws("Expected 'name' on object schema to be a string, got undefined");
});

function expectInvalidProperty(badProperty: Realm.PropertyType | Realm.ObjectSchemaProperty, message: string) {
function expectInvalidProperty(
badProperty: Realm.PropertyType | Realm.ObjectSchemaProperty,
message: string,
addMessagePrefix = true,
) {
if (addMessagePrefix) {
message = `Invalid type declaration for property 'bad' on 'InvalidObject': ${message}`;
}
expect(() => {
new Realm({
schema: [
Expand All @@ -205,18 +212,21 @@ describe("Realm#constructor", () => {
}

it("fails when asking for a list of lists", () => {
expectInvalidProperty({ type: "list[]" }, "List property 'InvalidObject#bad' cannot have list elements");
expectInvalidProperty(
{ type: "list", objectType: "list" },
"A list must contain only primitive or user-defined types specified through 'objectType'",
);
});

it("fails when asking for an optional list", () => {
it("fails when asking for an optional list of objects", () => {
expectInvalidProperty(
{ type: "list?", objectType: "InvalidObject" },
"List property 'InvalidObject#bad' of 'InvalidObject' elements, cannot be optional",
{ type: "list", objectType: "InvalidObject", optional: true },
"User-defined types in lists and sets are always non-optional and cannot be made optional",
);
});

it("fails when asking for an empty type string", () => {
expectInvalidProperty("", "Property 'InvalidObject#bad' cannot have an empty object type");
expectInvalidProperty("", "The type must be specified.");
});

it("fails when asking for linkingObjects to a non-existing property", () => {
Expand All @@ -227,6 +237,7 @@ describe("Realm#constructor", () => {
type: "linkingObjects",
},
"Property 'InvalidObject.nosuchproperty' declared as origin of linking objects property 'InvalidObject.bad' does not exist",
false,
);
});

Expand All @@ -238,6 +249,7 @@ describe("Realm#constructor", () => {
type: "linkingObjects",
},
"Property 'InvalidObject.nummeric' declared as origin of linking objects property 'InvalidObject.bad' is not a link",
false,
);
});

Expand All @@ -249,26 +261,9 @@ describe("Realm#constructor", () => {
type: "linkingObjects",
},
"Property 'InvalidObject.another' declared as origin of linking objects property 'InvalidObject.bad' links to type 'AnotherObject'",
false,
);
});

it("doesn't allow list of objects with objectType defined", () => {
expect(() => {
new Realm({
schema: [
{
name: "SomeObject",
properties: {
myObjects: {
objectType: "SomeObject",
type: "object[]",
},
},
},
],
});
}).throws("Expected no 'objectType' in property schema, when using '[]' shorthand");
});
});

// TODO: Next up is testRealmConstructorInMemory from realm-tests.js
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/tests/src/tests/serialization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ interface IPlaylist {
const BirthdaysSchema: Realm.ObjectSchema = {
name: "Birthdays",
properties: {
dict: "{}",
dict: "mixed{}",
},
};

Expand Down
2 changes: 1 addition & 1 deletion integration-tests/tests/src/tests/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe("Set", () => {
schema: [
{
name: "Item",
properties: { set: { type: "set" } },
properties: { set: { type: "set", objectType: "mixed" } },
},
{
name: "Person",
Expand Down
60 changes: 39 additions & 21 deletions packages/realm/src/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
////////////////////////////////////////////////////////////////////////////

import {
CanonicalObjectSchema,
CanonicalObjectSchemaProperty,
DefaultObject,
ObjectSchema,
ObjectSchemaProperty,
Expand Down Expand Up @@ -195,16 +197,32 @@ type BaseConfiguration = {
// disableFormatUpgrade?: boolean;
// };

const OBJECT_SCHEMA_KEYS = new Set<keyof ObjectSchema>(["name", "primaryKey", "embedded", "asymmetric", "properties"]);
// Need to use `CanonicalObjectSchema` rather than `ObjectSchema` due to some
// integration tests using `openRealmHook()`. That function sets `this.realm`
// to the opened realm whose schema is a `CanonicalObjectSchema[]`. Consequently,
// the key `"ctor"` (which doesn't exist on `ObjectSchema`) also needs to be allowed.
const OBJECT_SCHEMA_KEYS = new Set<keyof CanonicalObjectSchema>([
"name",
"primaryKey",
"embedded",
"asymmetric",
"properties",
// Not part of `ObjectSchema`
"ctor",
]);

const PROPERTY_SCHEMA_KEYS = new Set<keyof ObjectSchemaProperty>([
// Need to use `CanonicalObjectSchemaProperty` rather than `ObjectSchemaProperty`
// due to the same reasons as above.
const PROPERTY_SCHEMA_KEYS = new Set<keyof CanonicalObjectSchemaProperty>([
"type",
"objectType",
"property",
"default",
"optional",
"indexed",
"mapTo",
// Not part of `ObjectSchemaProperty`
"name",
]);

/**
Expand All @@ -231,7 +249,7 @@ export function validateConfiguration(config: unknown): asserts config is Config
* Validate the data types of the fields of a user-provided realm schema.
*/
export function validateRealmSchema(realmSchema: unknown): asserts realmSchema is Configuration["schema"][] {
assert.array(realmSchema, "the realm schema");
assert.array(realmSchema, "realm schema");
for (const objectSchema of realmSchema) {
validateObjectSchema(objectSchema);
}
Expand All @@ -244,8 +262,8 @@ export function validateRealmSchema(realmSchema: unknown): asserts realmSchema i
export function validateObjectSchema(
objectSchema: unknown,
): asserts objectSchema is RealmObjectConstructor | ObjectSchema {
// Schema is passed via a class based model (RealmObjectConstructor)
if (typeof objectSchema === "function") {
// Class based model
const clazz = objectSchema as unknown as DefaultObject;
// We assert this later, but want a custom error message
if (!(objectSchema.prototype instanceof RealmObject)) {
Expand All @@ -258,20 +276,21 @@ export function validateObjectSchema(
}
assert.object(clazz.schema, "schema static");
validateObjectSchema(clazz.schema);
} else {
// Schema is passed as an object
assert.object(objectSchema, "the object schema", false);
}
// Schema is passed as an object (ObjectSchema)
else {
assert.object(objectSchema, "object schema", { allowArrays: false });
const { name: objectName, properties, primaryKey, asymmetric, embedded } = objectSchema;
assert.string(objectName, "the object schema name");
assert.object(properties, `${objectName}.properties`, false);
assert.string(objectName, "'name' on object schema");
assert.object(properties, `'properties' on '${objectName}'`, { allowArrays: false });
if (primaryKey !== undefined) {
assert.string(primaryKey, `${objectName}.primaryKey`);
assert.string(primaryKey, `'primaryKey' on '${objectName}'`);
}
if (embedded !== undefined) {
assert.boolean(embedded, `${objectName}.embedded`);
assert.boolean(embedded, `'embedded' on '${objectName}'`);
}
if (asymmetric !== undefined) {
assert.boolean(asymmetric, `${objectName}.asymmetric`);
assert.boolean(asymmetric, `'asymmetric' on '${objectName}'`);
}

const invalidKeysUsed = filterInvalidKeys(objectSchema, OBJECT_SCHEMA_KEYS);
Expand Down Expand Up @@ -299,29 +318,28 @@ export function validatePropertySchema(
propertyName: string,
propertySchema: unknown,
): asserts propertySchema is ObjectSchemaProperty {
const displayedName = `${objectName}.${propertyName}`;
assert.object(propertySchema, displayedName, false);
assert.object(propertySchema, `'${propertyName}' on '${objectName}'`, { allowArrays: false });
const { type, objectType, optional, property, indexed, mapTo } = propertySchema;
assert.string(type, `${displayedName}.type`);
assert.string(type, `'${propertyName}.type' on '${objectName}'`);
if (objectType !== undefined) {
assert.string(objectType, `${displayedName}.objectType`);
assert.string(objectType, `'${propertyName}.objectType' on '${objectName}'`);
}
if (optional !== undefined) {
assert.boolean(optional, `${displayedName}.optional`);
assert.boolean(optional, `'${propertyName}.optional' on '${objectName}'`);
}
if (property !== undefined) {
assert.string(property, `${displayedName}.property`);
assert.string(property, `'${propertyName}.property' on '${objectName}'`);
}
if (indexed !== undefined) {
assert.boolean(indexed, `${displayedName}.indexed`);
assert.boolean(indexed, `'${propertyName}.indexed' on '${objectName}'`);
}
if (mapTo !== undefined) {
assert.string(mapTo, `${displayedName}.mapTo`);
assert.string(mapTo, `'${propertyName}.mapTo' on '${objectName}'`);
}
const invalidKeysUsed = filterInvalidKeys(propertySchema, PROPERTY_SCHEMA_KEYS);
assert(
!invalidKeysUsed.length,
`Unexpected field(s) found on the schema for property '${displayedName}': '${invalidKeysUsed.join("', '")}'.`,
`Unexpected field(s) found on the schema for property '${propertyName}' on '${objectName}': '${invalidKeysUsed.join("', '")}'.`,
);
}

Expand Down
Loading

0 comments on commit ccc36e0

Please sign in to comment.