diff --git a/packages/repository/src/__tests__/unit/repositories/constraint-utils.unit.ts b/packages/repository/src/__tests__/unit/repositories/constraint-utils.unit.ts index b06d0b832bbe..44d48f2f1064 100644 --- a/packages/repository/src/__tests__/unit/repositories/constraint-utils.unit.ts +++ b/packages/repository/src/__tests__/unit/repositories/constraint-utils.unit.ts @@ -5,14 +5,14 @@ import {expect} from '@loopback/testlab'; import { - FilterBuilder, - Filter, - Where, - constrainFilter, - constrainWhere, constrainDataObject, constrainDataObjects, + constrainFilter, + constrainWhere, Entity, + Filter, + FilterBuilder, + Where, } from '../../..'; describe('constraint utility functions', () => { @@ -87,7 +87,7 @@ describe('constraint utility functions', () => { }); }); - it('throws error when the query changes field in constrain', () => { + it('throws error when the query changes field in constraint', () => { const input = new Order({id: 1, description: 'order 1'}); const constraint: Partial = {id: 2}; expect(() => { @@ -95,16 +95,50 @@ describe('constraint utility functions', () => { }).to.throwError(/Property "id" cannot be changed!/); }); + it('allows constrained fields with the same values', () => { + const input = new Order({id: 2, description: 'order 1'}); + const constraint: Partial = {id: 2}; + const result = constrainDataObject(input, constraint); + expect(result).to.deepEqual( + new Order({ + id: 2, + description: 'order 1', + }), + ); + }); + }); + + describe('constrainDataObjects', () => { it('constrains array of data objects', () => { const input = [ - new Order({id: 1, description: 'order 1'}), - new Order({id: 2, description: 'order 2'}), + new Order({description: 'order 1'}), + new Order({description: 'order 2'}), ]; const constraint: Partial = {id: 3}; const result = constrainDataObjects(input, constraint); expect(result[0]).to.containDeep(Object.assign({}, input[0], constraint)); expect(result[1]).to.containDeep(Object.assign({}, input[1], constraint)); }); + + it('throws error when the query changes field in constraint', () => { + const input = [new Order({id: 1, description: 'order 1'})]; + const constraint: Partial = {id: 2}; + expect(() => { + constrainDataObjects(input, constraint); + }).to.throwError(/Property "id" cannot be changed!/); + }); + + it('allows constrained fields with the same values', () => { + const input = [new Order({id: 2, description: 'order 1'})]; + const constraint: Partial = {id: 2}; + const result = constrainDataObjects(input, constraint); + expect(result).to.deepEqual([ + new Order({ + id: 2, + description: 'order 1', + }), + ]); + }); }); /*---------------HELPERS----------------*/ diff --git a/packages/repository/src/repositories/constraint-utils.ts b/packages/repository/src/repositories/constraint-utils.ts index 20d1dc0b41c5..6d8afd0883f8 100644 --- a/packages/repository/src/repositories/constraint-utils.ts +++ b/packages/repository/src/repositories/constraint-utils.ts @@ -3,10 +3,10 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -import {Filter, WhereBuilder, Where, FilterBuilder} from '../query'; -import {AnyObject, DataObject} from '../common-types'; import {cloneDeep} from 'lodash'; +import {AnyObject, DataObject} from '../common-types'; import {Entity} from '../model'; +import {Filter, FilterBuilder, Where, WhereBuilder} from '../query'; /** * A utility function which takes a filter and enforces constraint(s) @@ -55,12 +55,16 @@ export function constrainDataObject( ): DataObject { const constrainedData = cloneDeep(originalData); for (const c in constraint) { - if (constrainedData.hasOwnProperty(c)) + if (constrainedData.hasOwnProperty(c)) { + // Known limitation: === does not work for objects such as ObjectId + if (originalData[c] === constraint[c]) continue; throw new Error(`Property "${c}" cannot be changed!`); + } (constrainedData as AnyObject)[c] = constraint[c]; } return constrainedData; } + /** * A utility function which takes an array of model instance data and * enforces constraint(s) on it @@ -71,13 +75,7 @@ export function constrainDataObject( */ export function constrainDataObjects( originalData: DataObject[], - constraint: Partial, + constraint: DataObject, ): DataObject[] { - const constrainedData = cloneDeep(originalData); - for (let obj of constrainedData) { - for (let prop in constraint) { - (obj as AnyObject)[prop] = constraint[prop]; - } - } - return constrainedData; + return originalData.map(obj => constrainDataObject(obj, constraint)); }