From 1b4489f9163215a2781b52540777268a2d2cb2db Mon Sep 17 00:00:00 2001 From: RobinBuschmann Date: Mon, 27 Nov 2017 20:29:20 +0100 Subject: [PATCH 1/2] closes #209 --- lib/utils/object.ts | 9 ++- test/specs/scopes.spec.ts | 97 ++++++++++++++++++++++++++------- test/specs/utils/object.spec.ts | 23 +++++++- 3 files changed, 106 insertions(+), 23 deletions(-) diff --git a/lib/utils/object.ts b/lib/utils/object.ts index 60f3ff26..592f30a9 100644 --- a/lib/utils/object.ts +++ b/lib/utils/object.ts @@ -15,11 +15,16 @@ export function deepAssign(target: any, ...sources: any[]): any { .getOwnPropertyNames(source) .forEach(key => assign(key, target, source)) ; + if (Object.getOwnPropertySymbols) { + Object + .getOwnPropertySymbols(source) + .forEach(key => assign(key, target, source)) + ; + } }); - return target; - function assign(key: string | number, _target: any, _source: any): void { + function assign(key: string | number | symbol, _target: any, _source: any): void { const sourceValue = _source[key]; if (sourceValue !== void 0) { diff --git a/test/specs/scopes.spec.ts b/test/specs/scopes.spec.ts index b7e4d281..28d779ae 100644 --- a/test/specs/scopes.spec.ts +++ b/test/specs/scopes.spec.ts @@ -1,12 +1,22 @@ import {expect, use} from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; +import {useFakeTimers} from 'sinon'; +import {Op} from 'sequelize'; import {createSequelize} from "../utils/sequelize"; import {getScopeOptions} from "../../lib/services/scopes"; import {ShoeWithScopes, SHOE_DEFAULT_SCOPE, SHOE_SCOPES} from "../models/ShoeWithScopes"; import {Manufacturer} from "../models/Manufacturer"; import {Person} from "../models/Person"; +import {Model} from '../../lib/models/Model'; +import {Table} from '../../lib/annotations/Table'; +import {Scopes} from '../../lib/annotations/Scopes'; +import {majorVersion} from '../../lib/utils/versioning'; +import {Column} from '../../lib/annotations/Column'; +import {UpdatedAt} from '../../lib/annotations/UpdatedAt'; +import chaiDatetime = require('chai-datetime'); use(chaiAsPromised); +use(chaiDatetime); describe('scopes', () => { @@ -92,30 +102,30 @@ describe('scopes', () => { it('should consider scopes and additional included model (object)', () => expect( (ShoeWithScopes.scope('full') as typeof ShoeWithScopes) - .findOne({ - include: [{ - model: Person, - }] - }) - .then(shoe => { - expect(shoe).to.have.property('manufacturer').which.is.not.null; - expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); - expect(shoe).to.have.property('owner').which.is.not.null; - }) + .findOne({ + include: [{ + model: Person, + }] + }) + .then(shoe => { + expect(shoe).to.have.property('manufacturer').which.is.not.null; + expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); + expect(shoe).to.have.property('owner').which.is.not.null; + }) ).not.to.be.rejected ); it('should consider scopes and additional included model (model)', () => expect( (ShoeWithScopes.scope('full') as typeof ShoeWithScopes) - .findOne({ - include: [Person] - }) - .then(shoe => { - expect(shoe).to.have.property('manufacturer').which.is.not.null; - expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); - expect(shoe).to.have.property('owner').which.is.not.null; - }) + .findOne({ + include: [Person] + }) + .then(shoe => { + expect(shoe).to.have.property('manufacturer').which.is.not.null; + expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); + expect(shoe).to.have.property('owner').which.is.not.null; + }) ).not.to.be.rejected ); @@ -134,7 +144,7 @@ describe('scopes', () => { it('should not consider default scope due to unscoped call, but additonal includes (model)', () => (ShoeWithScopes - .unscoped() as typeof ShoeWithScopes) + .unscoped() as typeof ShoeWithScopes) .findOne({ include: [Person] }) @@ -219,6 +229,55 @@ describe('scopes', () => { }); + if (majorVersion > 3) { + + describe('with symbols', () => { + const _sequelize = createSequelize(false); + + @Scopes({ + bob: {where: {name: {[Op.like]: '%bob%'}}}, + updated: {where: {updated: {[Op.gt]: new Date(2000, 1)}}}, + }) + @Table + class Person extends Model { + + @Column + name: string; + + @UpdatedAt + updated: Date; + } + + _sequelize.addModels([Person]); + + beforeEach(() => _sequelize.sync({force: true})); + + it('should consider symbols while finding elements', () => { + return Person + .create({name: '1bob2'}) + .then(() => Person.create({name: 'bob'})) + .then(() => Person.create({name: 'bobby'})) + .then(() => Person.create({name: 'robert'})) + .then(() => (Person.scope('bob') as typeof Person).findAll()) + .then(persons => expect(persons).to.have.property('length', 3)) + ; + }); + + it('should consider symbols on timestamp column while finding elements', () => { + const clock = useFakeTimers(+new Date()); + return Person + .create({name: 'test'}) + .then(() => (Person.scope('updated') as typeof Person).findAll()) + .then(() => Person.findAll()) + .then(persons => expect(persons).to.have.property('length', 1)) + .then(() => clock.restore()) + ; + }); + + }); + } + + }); }); diff --git a/test/specs/utils/object.spec.ts b/test/specs/utils/object.spec.ts index 055cbc76..ee3ab8a4 100644 --- a/test/specs/utils/object.spec.ts +++ b/test/specs/utils/object.spec.ts @@ -13,7 +13,14 @@ describe('utils', () => { const childSourceA = {f: childSourceF}; const childSourceB = {}; const source1 = {a: childSourceA, b: childSourceB, c: 1, d: 'd', over: 'ride', regex: /reg/gim, notNull: null}; - const source2 = {e: 'für elisa', g: () => null, arr: [{h: 1}, {}, 'e'], over: 'ridden', nullable: null, notNull: 'notNull'}; + const source2 = { + e: 'für elisa', + g: () => null, + arr: [{h: 1}, {}, 'e'], + over: 'ridden', + nullable: null, + notNull: 'notNull' + }; const sourceKeys = [].concat(Object.keys(source1), Object.keys(source2)); it('should not be undefined', () => { @@ -110,8 +117,10 @@ describe('utils', () => { it('should keep prototype chain', () => { class Test { - protoFn(): any {} + protoFn(): any { + } } + const copy = deepAssign({}, {test: new Test()}); expect(copy.test) @@ -119,6 +128,16 @@ describe('utils', () => { .that.is.a('function'); }); + if (Object.getOwnPropertySymbols) { + it('should copy symbol based objects', () => { + const symbol = Symbol('test'); + const value = 'test'; + const copy = deepAssign({}, {[symbol]: value}); + + expect(copy[symbol]).to.equal(value); + }); + } + }); }); From e043263c73e40895d44df4c31304d8c4305b33f8 Mon Sep 17 00:00:00 2001 From: RobinBuschmann Date: Mon, 27 Nov 2017 20:41:00 +0100 Subject: [PATCH 2/2] istanbul ignore added :O --- lib/utils/object.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils/object.ts b/lib/utils/object.ts index 592f30a9..7f25d401 100644 --- a/lib/utils/object.ts +++ b/lib/utils/object.ts @@ -15,6 +15,7 @@ export function deepAssign(target: any, ...sources: any[]): any { .getOwnPropertyNames(source) .forEach(key => assign(key, target, source)) ; + /* istanbul ignore next */ if (Object.getOwnPropertySymbols) { Object .getOwnPropertySymbols(source)