From 7eec7e4e34d68e1392365f38f692fb667fb5703a Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 17 Sep 2018 08:22:21 -0700 Subject: [PATCH 1/2] Allow List to take items as instances of a class --- lib/list.js | 11 ++++- test/list.test.js | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 test/list.test.js diff --git a/lib/list.js b/lib/list.js index e0acb7cd..331e3851 100644 --- a/lib/list.js +++ b/lib/list.js @@ -63,9 +63,13 @@ function List(items, itemType, parent) { }); } + List.prototype.toItem = function(item) { + return isClass(this.itemType) ? new this.itemType(item) : this.itemType(item); + }; + items.forEach(function(item, i) { if (itemType && !(item instanceof itemType)) { - arr[i] = itemType(item); + arr[i] = arr.toItem(item); } else { arr[i] = item; } @@ -79,7 +83,7 @@ util.inherits(List, Array); var _push = List.prototype.push; List.prototype.push = function(obj) { - var item = this.itemType && (obj instanceof this.itemType) ? obj : this.itemType(obj); + var item = this.itemType && (obj instanceof this.itemType) ? obj : this.toItem(obj); _push.call(this, item); return item; }; @@ -117,3 +121,6 @@ List.prototype.toString = function() { return JSON.stringify(this.toJSON()); }; +function isClass(fn) { + return fn && fn.toString().indexOf('class ') === 0; +} diff --git a/test/list.test.js b/test/list.test.js new file mode 100644 index 00000000..b1c1d9aa --- /dev/null +++ b/test/list.test.js @@ -0,0 +1,119 @@ +'use strict'; + +var should = require('./init.js'); +var List = require('../lib/list'); + +/** + * Phone as a class + */ +class Phone { + constructor(label, num) { + this.label = label; + this.num = num; + } + + toJSON() { + return { + label: this.label, + num: this.num, + }; + } +} + +/** + * Phone as a constructor function + * @param {string} label + * @param {number} num + */ +function PhoneCtor(label, num) { + if (!(this instanceof PhoneCtor)) { + return new PhoneCtor(label, num); + } + this.label = label; + this.num = num; +} + +describe('list of items typed by a class', function() { + it('allows itemType to be a class', function() { + var phones = givenPhones(); + + var list = new List(phones, Phone); + list.should.be.an.instanceOf(Array); + list.toJSON().should.be.eql(phones); + }); + + it('converts items of plain json to the itemType', function() { + var phones = givenPhonesAsJSON(); + + var list = new List(phones, Phone); + list[0].should.be.an.instanceOf(Phone); + }); + + it('converts stringified items to the itemType', function() { + var phones = givenPhonesAsJSON(); + + var list = new List(JSON.stringify(phones), Phone); + list[0].should.be.an.instanceOf(Phone); + }); + + it('converts items of plain json to the itemType with push', function() { + var phones = givenPhonesAsJSON(); + + var list = new List([], Phone); + list.push(phones[0]); + list[0].should.be.an.instanceOf(Phone); + }); +}); + +describe('list of items typed by a ctor', function() { + it('allows itemType to be a ctor', function() { + var phones = givenPhonesWithCtor(); + + var list = new List(phones, PhoneCtor); + list.should.be.an.instanceOf(Array); + list.toJSON().should.be.eql(phones); + }); + + it('converts items of plain json to the itemType', function() { + var phones = givenPhonesAsJSON(); + + var list = new List(phones, PhoneCtor); + list[0].should.be.an.instanceOf(PhoneCtor); + }); + + it('converts stringified items to the itemType', function() { + var phones = givenPhonesAsJSON(); + + var list = new List(JSON.stringify(phones), PhoneCtor); + list[0].should.be.an.instanceOf(PhoneCtor); + }); + + it('converts items of plain json to the itemType with push', function() { + var phones = givenPhonesAsJSON(); + + var list = new List([], PhoneCtor); + list.push(phones[0]); + list[0].should.be.an.instanceOf(PhoneCtor); + }); +}); + +function givenPhones() { + return [ + new Phone('home', '111-222-3333'), + new Phone('work', '111-222-5555'), + ]; +} + +function givenPhonesWithCtor() { + return [ + new PhoneCtor('home', '111-222-3333'), + PhoneCtor('work', '111-222-5555'), + ]; +} + +function givenPhonesAsJSON() { + return [ + {label: 'home', num: '111-222-3333'}, + {label: 'work', num: '111-222-5555'}, + ]; +} From 7c7bd56b2ed9c05adf4042df2c8f1e6acf1e6ec1 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 17 Sep 2018 09:00:12 -0700 Subject: [PATCH 2/2] Add IBM copyright and MIT license headers --- test/kv-memory.js | 5 +++++ test/kvao.suite.js | 5 +++++ test/list.test.js | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/test/kv-memory.js b/test/kv-memory.js index cca00560..1211ab71 100644 --- a/test/kv-memory.js +++ b/test/kv-memory.js @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2013,2016. All Rights Reserved. +// Node module: loopback-datasource-juggler +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + 'use strict'; var kvMemory = require('../lib/connectors/kv-memory'); var DataSource = require('..').DataSource; diff --git a/test/kvao.suite.js b/test/kvao.suite.js index a464d7a0..62c50750 100644 --- a/test/kvao.suite.js +++ b/test/kvao.suite.js @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2013,2016. All Rights Reserved. +// Node module: loopback-datasource-juggler +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + 'use strict'; var debug = require('debug')('test'); diff --git a/test/list.test.js b/test/list.test.js index b1c1d9aa..c8e4b5db 100644 --- a/test/list.test.js +++ b/test/list.test.js @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: loopback-datasource-juggler +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + 'use strict'; var should = require('./init.js');