Skip to content

Commit

Permalink
Improve test coverage for model class
Browse files Browse the repository at this point in the history
  • Loading branch information
Raymond Feng committed Jun 2, 2017
1 parent ab61c78 commit 6e3ce22
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 40 deletions.
24 changes: 15 additions & 9 deletions packages/repository/src/model.ts
Expand Up @@ -106,7 +106,9 @@ export class ModelDefinition {
if (ids) {
return ids.map(id => this.properties[id]);
}
return Object.values(this.properties).filter(prop => prop.id);
const idProps = Object.keys(this.properties)
.map(p => this.properties[p]).filter(prop => prop.id);
return idProps;
}
}

Expand All @@ -122,7 +124,8 @@ export abstract class Model {
*/
toJSON(): Object {
const json: AnyObject = {};
for (const p in this.definition.properties) {
const def = (<typeof Model> this.constructor).definition;
for (const p in def.properties) {
if (p in this) {
json[p] = this[p];
}
Expand All @@ -134,12 +137,14 @@ export abstract class Model {
* Convert to a plain object as DTO
*/
toObject(options?: Options): Object {
const obj: AnyObject = {};
if (options && options.ignoreUnknownProperties === false)
for (const p in this.definition.properties) {
if (p in this) {
let obj: AnyObject;
if (options && options.ignoreUnknownProperties === false) {
obj = {};
for (const p in this) {
obj[p] = this[p];
}
} else {
obj = this.toJSON();
}
return obj;
}
Expand Down Expand Up @@ -200,9 +205,10 @@ export abstract class Entity extends Model implements Persistable {
const idProps = this.definition.idProperties();
if (idProps.length === 1) {
where[idProps[0].name] = id;
}
for (const idProp of idProps) {
where[idProp.name] = id[idProp.name];
} else {
for (const idProp of idProps) {
where[idProp.name] = id[idProp.name];
}
}
return where;
}
Expand Down
56 changes: 39 additions & 17 deletions packages/repository/test/unit/decorator/model-and-relation.ts
Expand Up @@ -6,7 +6,7 @@
import { expect } from '@loopback/testlab';
import { model, property, MODEL_KEY, PROPERTY_KEY }
from '../../../src/decorators/model';
import { belongsTo, embedsOne, embedsMany, hasMany, referencesMany,
import { relation, hasOne, belongsTo, embedsOne, embedsMany, hasMany, referencesMany,
referencesOne, RELATION_KEY, RelationType } from '../../../src/decorators/relation';

import { Entity, ValueObject } from '../../../src/model';
Expand Down Expand Up @@ -40,8 +40,27 @@ describe('model decorator', () => {
description: string;
}

interface ICustomer {}

@model({ name: 'order' })
class Order extends Entity {
@property({
name: 'qty', mysql: {
column: 'QTY',
},
})
quantity: number;

@property({ name: 'id', id: true, generated: true })
id: string;
customerId: string;

@belongsTo({ target: 'Customer' })
customer: ICustomer; // TypeScript does not allow me to reference Customer here
}

@model()
class Customer extends Entity {
class Customer extends Entity implements ICustomer {
id: string;
email: string;
firstName: string;
Expand All @@ -61,23 +80,12 @@ describe('model decorator', () => {

@hasMany()
orders?: Order[];
}

@model({ name: 'order' })
class Order extends Entity {
@property({
name: 'qty', mysql: {
column: 'QTY',
},
})
quantity: number;

@property({ name: 'id', id: true, generated: true })
id: string;
customerId: string;
@hasOne()
lastOrder?: Order;

@belongsTo({ target: 'Customer' })
customer: Customer;
@relation({type: RelationType.hasMany})
recentOrders?: Order[];
}

// Skip the tests before we resolve the issue around global `Reflector`
Expand Down Expand Up @@ -139,4 +147,18 @@ describe('model decorator', () => {
});
});

it('adds hasOne metadata', () => {
const meta = Reflector.getOwnMetadata(RELATION_KEY, Customer.prototype, 'lastOrder');
expect(meta).to.eql({
type: RelationType.hasOne,
});
});

it('adds relation metadata', () => {
const meta = Reflector.getOwnMetadata(RELATION_KEY, Customer.prototype, 'recentOrders');
expect(meta).to.eql({
type: RelationType.hasMany,
});
});

});
124 changes: 110 additions & 14 deletions packages/repository/test/unit/model/model.ts
Expand Up @@ -9,22 +9,118 @@ import { Model, Entity, ModelDefinition, PropertyDefinition } from '../../../src

describe('model', () => {

const customerDef = new ModelDefinition('Customer');
customerDef.addProperty(new PropertyDefinition('id', 'string'))
.addProperty('email', 'string').addProperty('firstName', String)
.addProperty('lastName', STRING)
.addSetting('id', 'id');

const relamCustomerDef = new ModelDefinition('RealmCustomer');
relamCustomerDef.addProperty(new PropertyDefinition('realm', 'string'))
.addProperty('email', 'string').addProperty('firstName', String)
.addProperty('lastName', STRING)
.addSetting('id', ['realm', 'email']);

const userDef = new ModelDefinition('User');
const idProp = new PropertyDefinition('id', 'string');
idProp.id = true;
userDef.addProperty(idProp)
.addProperty('email', 'string').addProperty('firstName', String)
.addProperty('lastName', STRING);

class Customer extends Entity {
static modelName = 'Customer';
static definition = customerDef;
}

class RealmCustomer extends Entity {
static modelName = 'RealmCustomer';
static definition = relamCustomerDef;
}

class User extends Entity {
static modelName = 'User';
static definition = userDef;
}

function createCustomer() {
const customer = new Customer();
customer.id = '123';
customer.email = 'xyz@example.com';
return customer;
}

function createRealmCustomer() {
const customer = new RealmCustomer();
customer.realm = 'org1';
customer.email = 'xyz@example.com';
return customer;
}

it('adds properties', () => {
const modelDef = new ModelDefinition('Customer');
modelDef.addProperty(new PropertyDefinition('id', 'string'))
.addProperty('email', 'string').addProperty('firstName', String)
.addProperty('lastName', STRING)
.addSetting('key', ['id']);
expect(modelDef.name).to.eql('Customer');
expect(modelDef.properties).have.properties('id', 'email', 'lastName', 'firstName');
expect(modelDef.properties.lastName).to.eql(
expect(customerDef.name).to.eql('Customer');
expect(customerDef.properties).have.properties('id', 'email', 'lastName', 'firstName');
expect(customerDef.properties.lastName).to.eql(
new PropertyDefinition('lastName', STRING));
});

/*
class CustomerModel extends Entity {
static modelName = 'Customer';
static definition = modelDef;
}
*/
it('adds settings', () => {
expect(customerDef.settings).have.property('id', 'id');
});

it('lists id properties', () => {
expect(customerDef.idProperties()).to.eql([customerDef.properties.id]);
expect(userDef.idProperties()).to.eql([userDef.properties.id]);
expect(relamCustomerDef.idProperties()).to.eql([
relamCustomerDef.properties.realm,
relamCustomerDef.properties.email,
]);
});

it('converts to json', () => {
const customer = createCustomer();
expect(customer.toJSON()).to.eql({ id: '123', email: 'xyz@example.com' });
});

it('converts to plain object', () => {
const customer = createCustomer();
customer.unknown = 'abc';
expect(customer.toObject()).to.eql({ id: '123', email: 'xyz@example.com' });
expect(customer.toObject({ignoreUnknownProperties: false}))
.to.eql({ id: '123', email: 'xyz@example.com', unknown: 'abc' });
});

it('gets id', () => {
const customer = createCustomer();
expect(customer.getId()).to.eql('123');
});

it('gets id object', () => {
const customer = createCustomer();
expect(customer.getIdObject()).to.eql({id: '123'});
});

it('builds where for id', () => {
const where = Customer.buildWhereForId('123');
expect(where).to.eql({id: '123'});
});

it('gets composite id', () => {
const customer = createRealmCustomer();
expect(customer.getId()).to.eql(
{realm: 'org1', email: 'xyz@example.com'});
});

it('gets composite id object', () => {
const customer = createRealmCustomer();
expect(customer.getIdObject()).to.eql(
{realm: 'org1', email: 'xyz@example.com'});
});

it('builds where for composite id', () => {
const where = RealmCustomer.buildWhereForId(
{realm: 'org1', email: 'xyz@example.com'});
expect(where).to.eql({realm: 'org1', email: 'xyz@example.com'});
});

});

0 comments on commit 6e3ce22

Please sign in to comment.