Change the recommended model declaration to allow models inheritance.
All checks were successful
/ test (push) Successful in 37s
All checks were successful
/ test (push) Successful in 37s
This commit is contained in:
parent
5f1e2709bb
commit
72417dd350
2 changed files with 156 additions and 149 deletions
145
README.md
145
README.md
|
@ -45,23 +45,23 @@ Then, you can use the defined methods like `serialize`, `parse`, `patch` or `ser
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class Example {
|
class Example {
|
||||||
static model = defineModel({
|
|
||||||
Class: Example,
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
name: s.property.string(),
|
|
||||||
},
|
|
||||||
identifier: "id",
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExampleModel = defineModel({
|
||||||
|
Class: Example,
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
name: s.property.string(),
|
||||||
|
},
|
||||||
|
identifier: "id",
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
**Note**: by convention, we define our models in a `model` static variable in the model's class. It is a good way to keep your model declaration near the actual class, and its usage will be more natural.
|
**Note**: we usually define our models in a `{ModelName}Model` variable next to the model's class.
|
||||||
|
|
||||||
### Model definition
|
### Model definition
|
||||||
|
|
||||||
|
@ -70,24 +70,27 @@ class Example {
|
||||||
* A person.
|
* A person.
|
||||||
*/
|
*/
|
||||||
class Person {
|
class Person {
|
||||||
static model = defineModel({
|
|
||||||
Class: Person,
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
name: s.property.string(),
|
|
||||||
email: s.property.string(),
|
|
||||||
createdAt: s.property.date(),
|
|
||||||
active: s.property.boolean(),
|
|
||||||
},
|
|
||||||
identifier: "id",
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
active: boolean = true;
|
active: boolean = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A person model manager.
|
||||||
|
*/
|
||||||
|
const PersonModel = defineModel({
|
||||||
|
Class: Person,
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
name: s.property.string(),
|
||||||
|
email: s.property.string(),
|
||||||
|
createdAt: s.property.date(),
|
||||||
|
active: s.property.boolean(),
|
||||||
|
},
|
||||||
|
identifier: "id",
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
@ -95,23 +98,6 @@ class Person {
|
||||||
* An article.
|
* An article.
|
||||||
*/
|
*/
|
||||||
class Article {
|
class Article {
|
||||||
static model = defineModel({
|
|
||||||
Class: Article,
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
title: s.property.string(),
|
|
||||||
authors: s.property.array(s.property.model(Person)),
|
|
||||||
text: s.property.string(),
|
|
||||||
evaluation: s.property.decimal(),
|
|
||||||
tags: s.property.array(
|
|
||||||
s.property.object({
|
|
||||||
name: s.property.string(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
identifier: "id",
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
authors: Person[] = [];
|
authors: Person[] = [];
|
||||||
|
@ -121,6 +107,26 @@ class Article {
|
||||||
name: string;
|
name: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An article model manager.
|
||||||
|
*/
|
||||||
|
const ArticleModel = defineModel({
|
||||||
|
Class: Article,
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
title: s.property.string(),
|
||||||
|
authors: s.property.array(s.property.model(PersonModel)),
|
||||||
|
text: s.property.string(),
|
||||||
|
evaluation: s.property.decimal(),
|
||||||
|
tags: s.property.array(
|
||||||
|
s.property.object({
|
||||||
|
name: s.property.string(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
identifier: "id",
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
@ -128,18 +134,21 @@ class Article {
|
||||||
* A model with composite keys.
|
* A model with composite keys.
|
||||||
*/
|
*/
|
||||||
class CompositeKeys {
|
class CompositeKeys {
|
||||||
static model = defineModel({
|
|
||||||
Class: CompositeKeys,
|
|
||||||
properties: {
|
|
||||||
id1: s.property.numeric(),
|
|
||||||
id2: s.property.string(),
|
|
||||||
},
|
|
||||||
identifier: ["id1", "id2"],
|
|
||||||
});
|
|
||||||
|
|
||||||
id1: number;
|
id1: number;
|
||||||
id2: string;
|
id2: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A composite keys model manager.
|
||||||
|
*/
|
||||||
|
const CompositeKeysModel = defineModel({
|
||||||
|
Class: CompositeKeys,
|
||||||
|
properties: {
|
||||||
|
id1: s.property.numeric(),
|
||||||
|
id2: s.property.string(),
|
||||||
|
},
|
||||||
|
identifier: ["id1", "id2"],
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Model functions
|
### Model functions
|
||||||
|
@ -153,14 +162,14 @@ instance.createdAt = new Date();
|
||||||
instance.name = "John Doe";
|
instance.name = "John Doe";
|
||||||
instance.email = "john@doe.test";
|
instance.email = "john@doe.test";
|
||||||
instance.active = true;
|
instance.active = true;
|
||||||
const serialized = Person.model.model(instance).serialize();
|
const serialized = PersonModel.model(instance).serialize();
|
||||||
console.log(serialized); // { id: 1, createdAt: "YYYY-MM-DDTHH:mm:ss.sssZ", name: "John Doe", email: "john@doe.test", active: true }
|
console.log(serialized); // { id: 1, createdAt: "YYYY-MM-DDTHH:mm:ss.sssZ", name: "John Doe", email: "john@doe.test", active: true }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Deserialization
|
#### Deserialization
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const instance = Person.model.parse({
|
const instance = PersonModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
createdAt: "2011-10-05T14:48:00.000Z",
|
createdAt: "2011-10-05T14:48:00.000Z",
|
||||||
name: "John Doe",
|
name: "John Doe",
|
||||||
|
@ -174,7 +183,7 @@ console.log(instance.createdAt instanceof Date); // true
|
||||||
#### Patch
|
#### Patch
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const instance = Person.model.parse({
|
const instance = PersonModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
createdAt: "2011-10-05T14:48:00.000Z",
|
createdAt: "2011-10-05T14:48:00.000Z",
|
||||||
name: "John Doe",
|
name: "John Doe",
|
||||||
|
@ -185,9 +194,9 @@ const instance = Person.model.parse({
|
||||||
instance.name = "Johnny";
|
instance.name = "Johnny";
|
||||||
|
|
||||||
// Patch serialized only changed properties and the identifier.
|
// Patch serialized only changed properties and the identifier.
|
||||||
console.log(Person.model.model(instance).patch()); // { id: 1, name: "Johnny" }
|
console.log(PersonModel.model(instance).patch()); // { id: 1, name: "Johnny" }
|
||||||
// If you run it one more time, already patched properties will not be included again.
|
// If you run it one more time, already patched properties will not be included again.
|
||||||
console.log(Person.model.model(instance).patch()); // { id: 1 }
|
console.log(PersonModel.model(instance).patch()); // { id: 1 }
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Identifier
|
#### Identifier
|
||||||
|
@ -196,7 +205,7 @@ console.log(Person.model.model(instance).patch()); // { id: 1 }
|
||||||
const instance = new CompositeKeys();
|
const instance = new CompositeKeys();
|
||||||
instance.id1 = 5;
|
instance.id1 = 5;
|
||||||
instance.id2 = "foo";
|
instance.id2 = "foo";
|
||||||
const instanceIdentifier = CompositeKeys.model.model(instance).getIdentifier();
|
const instanceIdentifier = CompositeKeysModel.model(instance).getIdentifier();
|
||||||
console.log(instanceIdentifier); // [5, "foo"]
|
console.log(instanceIdentifier); // [5, "foo"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -222,15 +231,15 @@ When you are defining a property of a Sharkitek model, you must provide its type
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class Example {
|
class Example {
|
||||||
static model = defineModel({
|
|
||||||
Class: Example,
|
|
||||||
properties: {
|
|
||||||
foo: s.property.define(new StringType()),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
foo: string;
|
foo: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExampleModel = defineModel({
|
||||||
|
Class: Example,
|
||||||
|
properties: {
|
||||||
|
foo: s.property.define(new StringType()),
|
||||||
|
},
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
To ease the use of these classes and reduce read complexity, properties of each type are easily definable with a function for each type.
|
To ease the use of these classes and reduce read complexity, properties of each type are easily definable with a function for each type.
|
||||||
|
@ -249,15 +258,15 @@ Type implementers should provide a corresponding function for each defined type.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class Example {
|
class Example {
|
||||||
static model = defineModel({
|
|
||||||
Class: Example,
|
|
||||||
properties: {
|
|
||||||
foo: s.property.string(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
foo: string;
|
foo: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExampleModel = defineModel({
|
||||||
|
Class: Example,
|
||||||
|
properties: {
|
||||||
|
foo: s.property.string(),
|
||||||
|
},
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Models
|
### Models
|
||||||
|
|
|
@ -5,18 +5,6 @@ import {circular, defineModel, s} from "../src/library";
|
||||||
* Test class of an account.
|
* Test class of an account.
|
||||||
*/
|
*/
|
||||||
class Account {
|
class Account {
|
||||||
static model = s.defineModel({
|
|
||||||
Class: Account,
|
|
||||||
identifier: "id",
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
createdAt: s.property.date(),
|
|
||||||
name: s.property.string(),
|
|
||||||
email: s.property.string(),
|
|
||||||
active: s.property.boolean(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -24,24 +12,22 @@ class Account {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AccountModel = s.defineModel({
|
||||||
|
Class: Account,
|
||||||
|
identifier: "id",
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
createdAt: s.property.date(),
|
||||||
|
name: s.property.string(),
|
||||||
|
email: s.property.string(),
|
||||||
|
active: s.property.boolean(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class of an article.
|
* Test class of an article.
|
||||||
*/
|
*/
|
||||||
class Article {
|
class Article {
|
||||||
static model = s.defineModel({
|
|
||||||
Class: Article,
|
|
||||||
identifier: "id",
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
title: s.property.string(),
|
|
||||||
authors: s.property.array(s.property.model(() => Account.model)),
|
|
||||||
text: s.property.string(),
|
|
||||||
evaluation: s.property.decimal(),
|
|
||||||
tags: s.property.array(s.property.object({name: s.property.string()})),
|
|
||||||
comments: s.property.array(s.property.model(() => ArticleComment.model)),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
authors: Account[];
|
authors: Account[];
|
||||||
|
@ -51,27 +37,41 @@ class Article {
|
||||||
comments: ArticleComment[];
|
comments: ArticleComment[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ArticleModel = s.defineModel({
|
||||||
|
Class: Article,
|
||||||
|
identifier: "id",
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
title: s.property.string(),
|
||||||
|
authors: s.property.array(s.property.model(() => AccountModel)),
|
||||||
|
text: s.property.string(),
|
||||||
|
evaluation: s.property.decimal(),
|
||||||
|
tags: s.property.array(s.property.object({name: s.property.string()})),
|
||||||
|
comments: s.property.array(s.property.model(() => ArticleCommentModel)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class of a comment on an article.
|
* Test class of a comment on an article.
|
||||||
*/
|
*/
|
||||||
class ArticleComment {
|
class ArticleComment {
|
||||||
static model = s.defineModel({
|
|
||||||
Class: ArticleComment,
|
|
||||||
identifier: "id",
|
|
||||||
properties: {
|
|
||||||
id: s.property.numeric(),
|
|
||||||
article: s.property.model(circular<Article>(() => Article.model)),
|
|
||||||
author: s.property.model(() => Account.model),
|
|
||||||
message: s.property.string(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
article?: Article;
|
article?: Article;
|
||||||
author: Account;
|
author: Account;
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ArticleCommentModel = s.defineModel({
|
||||||
|
Class: ArticleComment,
|
||||||
|
identifier: "id",
|
||||||
|
properties: {
|
||||||
|
id: s.property.numeric(),
|
||||||
|
article: s.property.model(circular<Article>(() => ArticleModel)),
|
||||||
|
author: s.property.model(() => AccountModel),
|
||||||
|
message: s.property.string(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a test account instance.
|
* Get a test account instance.
|
||||||
*/
|
*/
|
||||||
|
@ -100,17 +100,17 @@ function getTestArticle(): Article {
|
||||||
describe("model", () => {
|
describe("model", () => {
|
||||||
it("defines a new model, extending an existing one", () => {
|
it("defines a new model, extending an existing one", () => {
|
||||||
class ExtendedAccount extends Account {
|
class ExtendedAccount extends Account {
|
||||||
static extendedModel = s.extend(Account.model, {
|
|
||||||
Class: ExtendedAccount,
|
|
||||||
properties: {
|
|
||||||
extendedProperty: s.property.string(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
extendedProperty: string;
|
extendedProperty: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(ExtendedAccount.extendedModel.definition).toEqual({
|
const ExtendedAccountModel = s.extend(AccountModel, {
|
||||||
|
Class: ExtendedAccount,
|
||||||
|
properties: {
|
||||||
|
extendedProperty: s.property.string(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(ExtendedAccountModel.definition).toEqual({
|
||||||
Class: ExtendedAccount,
|
Class: ExtendedAccount,
|
||||||
identifier: "id",
|
identifier: "id",
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -125,17 +125,17 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
it("initializes a new model", () => {
|
it("initializes a new model", () => {
|
||||||
const article = getTestArticle();
|
const article = getTestArticle();
|
||||||
const newModel = Article.model.model(article);
|
const newModel = ArticleModel.model(article);
|
||||||
expect(newModel.instance).toBe(article);
|
expect(newModel.instance).toBe(article);
|
||||||
});
|
});
|
||||||
it("gets a model state from its instance", () => {
|
it("gets a model state from its instance", () => {
|
||||||
const article = getTestArticle();
|
const article = getTestArticle();
|
||||||
expect(Article.model.model(article).isNew()).toBeTruthy();
|
expect(ArticleModel.model(article).isNew()).toBeTruthy();
|
||||||
expect(Article.model.model(article).isDirty()).toBeFalsy();
|
expect(ArticleModel.model(article).isDirty()).toBeFalsy();
|
||||||
});
|
});
|
||||||
it("gets a model identifier value", () => {
|
it("gets a model identifier value", () => {
|
||||||
const article = getTestArticle();
|
const article = getTestArticle();
|
||||||
expect(Article.model.model(article).getIdentifier()).toBe(1);
|
expect(ArticleModel.model(article).getIdentifier()).toBe(1);
|
||||||
});
|
});
|
||||||
it("gets a model composite identifier value", () => {
|
it("gets a model composite identifier value", () => {
|
||||||
class CompositeModel {
|
class CompositeModel {
|
||||||
|
@ -168,11 +168,11 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
it("checks model dirtiness when altered, then reset diff", () => {
|
it("checks model dirtiness when altered, then reset diff", () => {
|
||||||
const article = getTestArticle();
|
const article = getTestArticle();
|
||||||
expect(Article.model.model(article).isDirty()).toBeFalsy();
|
expect(ArticleModel.model(article).isDirty()).toBeFalsy();
|
||||||
article.title = "new title";
|
article.title = "new title";
|
||||||
expect(Article.model.model(article).isDirty()).toBeTruthy();
|
expect(ArticleModel.model(article).isDirty()).toBeTruthy();
|
||||||
Article.model.model(article).resetDiff();
|
ArticleModel.model(article).resetDiff();
|
||||||
expect(Article.model.model(article).isDirty()).toBeFalsy();
|
expect(ArticleModel.model(article).isDirty()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("deserializes a model from a serialized form", () => {
|
it("deserializes a model from a serialized form", () => {
|
||||||
|
@ -213,7 +213,7 @@ describe("model", () => {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const deserializedArticle = Article.model.parse({
|
const deserializedArticle = ArticleModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
|
@ -250,16 +250,14 @@ describe("model", () => {
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const deserializedArticleProperties = Article.model
|
const deserializedArticleProperties =
|
||||||
.model(deserializedArticle)
|
ArticleModel.model(deserializedArticle).getInstanceProperties();
|
||||||
.getInstanceProperties();
|
|
||||||
delete deserializedArticleProperties.authors[0]._sharkitek;
|
delete deserializedArticleProperties.authors[0]._sharkitek;
|
||||||
delete deserializedArticleProperties.authors[1]._sharkitek;
|
delete deserializedArticleProperties.authors[1]._sharkitek;
|
||||||
delete deserializedArticleProperties.comments[0]._sharkitek;
|
delete deserializedArticleProperties.comments[0]._sharkitek;
|
||||||
delete (deserializedArticleProperties.comments[0].author as any)._sharkitek;
|
delete (deserializedArticleProperties.comments[0].author as any)._sharkitek;
|
||||||
const expectedArticleProperties = Article.model
|
const expectedArticleProperties =
|
||||||
.model(expectedArticle)
|
ArticleModel.model(expectedArticle).getInstanceProperties();
|
||||||
.getInstanceProperties();
|
|
||||||
delete expectedArticleProperties.authors[0]._sharkitek;
|
delete expectedArticleProperties.authors[0]._sharkitek;
|
||||||
delete expectedArticleProperties.authors[1]._sharkitek;
|
delete expectedArticleProperties.authors[1]._sharkitek;
|
||||||
delete expectedArticleProperties.comments[0]._sharkitek;
|
delete expectedArticleProperties.comments[0]._sharkitek;
|
||||||
|
@ -269,7 +267,7 @@ describe("model", () => {
|
||||||
|
|
||||||
it("serializes an initialized model", () => {
|
it("serializes an initialized model", () => {
|
||||||
const article = getTestArticle();
|
const article = getTestArticle();
|
||||||
expect(Article.model.model(article).serialize()).toEqual({
|
expect(ArticleModel.model(article).serialize()).toEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
text: "this is a long test.",
|
text: "this is a long test.",
|
||||||
|
@ -289,7 +287,7 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("deserializes, changes and patches", () => {
|
it("deserializes, changes and patches", () => {
|
||||||
const deserializedArticle = Article.model.parse({
|
const deserializedArticle = ArticleModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
|
@ -328,21 +326,21 @@ describe("model", () => {
|
||||||
|
|
||||||
deserializedArticle.text = "A new text for a new life!";
|
deserializedArticle.text = "A new text for a new life!";
|
||||||
|
|
||||||
expect(Article.model.model(deserializedArticle).patch()).toStrictEqual({
|
expect(ArticleModel.model(deserializedArticle).patch()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
text: "A new text for a new life!",
|
text: "A new text for a new life!",
|
||||||
});
|
});
|
||||||
|
|
||||||
deserializedArticle.evaluation = 5.24;
|
deserializedArticle.evaluation = 5.24;
|
||||||
|
|
||||||
expect(Article.model.model(deserializedArticle).patch()).toStrictEqual({
|
expect(ArticleModel.model(deserializedArticle).patch()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
evaluation: "5.24",
|
evaluation: "5.24",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("patches with modified submodels", () => {
|
it("patches with modified submodels", () => {
|
||||||
const deserializedArticle = Article.model.parse({
|
const deserializedArticle = ArticleModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
|
@ -381,14 +379,14 @@ describe("model", () => {
|
||||||
|
|
||||||
deserializedArticle.authors[1].active = true;
|
deserializedArticle.authors[1].active = true;
|
||||||
|
|
||||||
expect(Article.model.model(deserializedArticle).patch()).toStrictEqual({
|
expect(ArticleModel.model(deserializedArticle).patch()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
authors: [{id: 52}, {id: 4, active: true}],
|
authors: [{id: 52}, {id: 4, active: true}],
|
||||||
});
|
});
|
||||||
|
|
||||||
deserializedArticle.comments[0].author.name = "Johnny";
|
deserializedArticle.comments[0].author.name = "Johnny";
|
||||||
|
|
||||||
expect(Article.model.model(deserializedArticle).patch()).toStrictEqual({
|
expect(ArticleModel.model(deserializedArticle).patch()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
comments: [
|
comments: [
|
||||||
{
|
{
|
||||||
|
@ -454,7 +452,7 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("assigns properties, ignoring fields which are not properties", () => {
|
it("assigns properties, ignoring fields which are not properties", () => {
|
||||||
const deserializedArticle = Article.model.parse({
|
const deserializedArticle = ArticleModel.parse({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
|
@ -492,13 +490,13 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assign title and text, html is silently ignored.
|
// Assign title and text, html is silently ignored.
|
||||||
Article.model.model(deserializedArticle).assign({
|
ArticleModel.model(deserializedArticle).assign({
|
||||||
title: "something else",
|
title: "something else",
|
||||||
text: "fully new text! yes!",
|
text: "fully new text! yes!",
|
||||||
html: "<p>fully new text! yes!</p>",
|
html: "<p>fully new text! yes!</p>",
|
||||||
});
|
});
|
||||||
expect((deserializedArticle as any)?.html).toBeUndefined();
|
expect((deserializedArticle as any)?.html).toBeUndefined();
|
||||||
expect(Article.model.model(deserializedArticle).patch()).toStrictEqual({
|
expect(ArticleModel.model(deserializedArticle).patch()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "something else",
|
title: "something else",
|
||||||
text: "fully new text! yes!",
|
text: "fully new text! yes!",
|
||||||
|
@ -506,10 +504,10 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("initializes a model from properties values", () => {
|
it("initializes a model from properties values", () => {
|
||||||
const testArticle = Article.model.from({
|
const testArticle = ArticleModel.from({
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
Account.model.from({
|
AccountModel.from({
|
||||||
name: "John Doe",
|
name: "John Doe",
|
||||||
email: "test@test.test",
|
email: "test@test.test",
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
@ -534,11 +532,11 @@ describe("model", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies patches to an existing model", () => {
|
it("applies patches to an existing model", () => {
|
||||||
const testArticle = Article.model.from({
|
const testArticle = ArticleModel.from({
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "this is a test",
|
title: "this is a test",
|
||||||
authors: [
|
authors: [
|
||||||
Account.model.from({
|
AccountModel.from({
|
||||||
id: 55,
|
id: 55,
|
||||||
name: "John Doe",
|
name: "John Doe",
|
||||||
email: "test@test.test",
|
email: "test@test.test",
|
||||||
|
@ -553,35 +551,35 @@ describe("model", () => {
|
||||||
unknownField: true,
|
unknownField: true,
|
||||||
anotherOne: "test",
|
anotherOne: "test",
|
||||||
});
|
});
|
||||||
Article.model.model(testArticle).resetDiff();
|
ArticleModel.model(testArticle).resetDiff();
|
||||||
|
|
||||||
// Test simple patch.
|
// Test simple patch.
|
||||||
Article.model.model(testArticle).applyPatch({
|
ArticleModel.model(testArticle).applyPatch({
|
||||||
title: "new title",
|
title: "new title",
|
||||||
});
|
});
|
||||||
expect(testArticle.title).toBe("new title");
|
expect(testArticle.title).toBe("new title");
|
||||||
expect(Article.model.model(testArticle).serializeDiff()).toStrictEqual({
|
expect(ArticleModel.model(testArticle).serializeDiff()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test originals update propagation.
|
// Test originals update propagation.
|
||||||
Article.model.model(testArticle).applyPatch({
|
ArticleModel.model(testArticle).applyPatch({
|
||||||
authors: [{email: "john@test.test"}],
|
authors: [{email: "john@test.test"}],
|
||||||
});
|
});
|
||||||
expect(testArticle.authors[0].email).toBe("john@test.test");
|
expect(testArticle.authors[0].email).toBe("john@test.test");
|
||||||
expect(Article.model.model(testArticle).serializeDiff()).toStrictEqual({
|
expect(ArticleModel.model(testArticle).serializeDiff()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test without originals update.
|
// Test without originals update.
|
||||||
Article.model.model(testArticle).applyPatch(
|
ArticleModel.model(testArticle).applyPatch(
|
||||||
{
|
{
|
||||||
authors: [{name: "Johnny"}],
|
authors: [{name: "Johnny"}],
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
expect(testArticle.authors[0].name).toBe("Johnny");
|
expect(testArticle.authors[0].name).toBe("Johnny");
|
||||||
expect(Article.model.model(testArticle).serializeDiff()).toStrictEqual({
|
expect(ArticleModel.model(testArticle).serializeDiff()).toStrictEqual({
|
||||||
id: 1,
|
id: 1,
|
||||||
authors: [{id: 55, name: "Johnny"}],
|
authors: [{id: 55, name: "Johnny"}],
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue