[Pkg-javascript-commits] [node-object-path] 01/04: Import Upstream version 0.11.3

Paolo Greppi paolog-guest at moszumanska.debian.org
Mon Dec 12 07:48:42 UTC 2016


This is an automated email from the git hooks/post-receive script.

paolog-guest pushed a commit to branch master
in repository node-object-path.

commit ed2018c44242d92bd8240053b4fc7329d66a7327
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date:   Mon Dec 12 07:39:14 2016 +0000

    Import Upstream version 0.11.3
---
 .npmignore     |   7 +
 .travis.yml    |   8 +
 LICENSE        |  21 ++
 README.md      | 180 ++++++++++++
 benchmark.js   |  52 ++++
 bower.json     |  16 +
 component.json |  22 ++
 index.js       | 291 ++++++++++++++++++
 package.json   |  45 +++
 test.js        | 913 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 1555 insertions(+)

diff --git a/.npmignore b/.npmignore
new file mode 100755
index 0000000..f35bd02
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,7 @@
+node_modules
+.settings
+.idea
+npm-debug.log
+generated
+coverage
+.DS_Store
diff --git a/.travis.yml b/.travis.yml
new file mode 100755
index 0000000..b4d505b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+sudo: false
+language: node_js
+node_js:
+  - "0.12"
+  - "0.10"
+  - "4"
+  - "6"
+after_script: NODE_ENV=test istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..356cc4c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Mario Casciaro
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2993b75
--- /dev/null
+++ b/README.md
@@ -0,0 +1,180 @@
+
+
+object-path
+===========
+
+Access deep properties using a path
+
+[![NPM version](https://badge.fury.io/js/object-path.png)](http://badge.fury.io/js/object-path)
+[![Build Status](https://travis-ci.org/mariocasciaro/object-path.png)](https://travis-ci.org/mariocasciaro/object-path)
+[![Coverage Status](https://coveralls.io/repos/mariocasciaro/object-path/badge.png)](https://coveralls.io/r/mariocasciaro/object-path)
+[![devDependency Status](https://david-dm.org/mariocasciaro/object-path/dev-status.svg)](https://david-dm.org/mariocasciaro/object-path#info=devDependencies)
+![Downloads](http://img.shields.io/npm/dm/object-path.svg)
+
+
+## Changelog
+
+### 0.11.0
+
+* Introduce ability to specify options and create new instances of `object-path`
+* Introduce option to control the way `object-path` deals with inherited properties (`includeInheritedProps`)
+* New default `object-path` instance already configured to handle not-own object properties (`withInheritedProps`)
+
+### 0.10.0
+
+* Improved performance of `get`, `set`, and `push` by 2x-3x
+* Introduced a benchmarking test suite
+* **BREAKING CHANGE**: `del`, `empty`, `set` will not affect not-own object's properties (made them consistent with the other methods)
+
+## Install
+
+### Node.js
+
+```
+npm install object-path --save
+```
+
+### Bower
+
+```
+bower install object-path --save
+```
+
+### Typescript typings
+
+```
+tsd query object-path --action install --save
+```
+
+## Usage
+
+```javascript
+
+var obj = {
+  a: {
+    b: "d",
+    c: ["e", "f"],
+    '\u1200': 'unicode key',
+    'dot.dot': 'key'
+  }
+};
+
+var objectPath = require("object-path");
+
+//get deep property
+objectPath.get(obj, "a.b");  //returns "d"
+objectPath.get(obj, ["a", "dot.dot"]);  //returns "key"
+objectPath.get(obj, 'a.\u1200');  //returns "unicode key"
+
+//get the first non-undefined value
+objectPath.coalesce(obj, ['a.z', 'a.d', ['a','b']], 'default');
+
+//empty a given path (but do not delete it) depending on their type,so it retains reference to objects and arrays.
+//functions that are not inherited from prototype are set to null.
+//object instances are considered objects and just own property names are deleted
+objectPath.empty(obj, 'a.b'); // obj.a.b is now ''
+objectPath.empty(obj, 'a.c'); // obj.a.c is now []
+objectPath.empty(obj, 'a'); // obj.a is now {}
+
+//works also with arrays
+objectPath.get(obj, "a.c.1");  //returns "f"
+objectPath.get(obj, ["a","c","1"]);  //returns "f"
+
+//can return a default value with get
+objectPath.get(obj, ["a.c.b"], "DEFAULT");  //returns "DEFAULT", since a.c.b path doesn't exists, if omitted, returns undefined
+
+//set
+objectPath.set(obj, "a.h", "m"); // or objectPath.set(obj, ["a","h"], "m");
+objectPath.get(obj, "a.h");  //returns "m"
+
+//set will create intermediate object/arrays
+objectPath.set(obj, "a.j.0.f", "m");
+
+//will insert values in array
+objectPath.insert(obj, "a.c", "m", 1); // obj.a.c = ["e", "m", "f"]
+
+//push into arrays (and create intermediate objects/arrays)
+objectPath.push(obj, "a.k", "o");
+
+//ensure a path exists (if it doesn't, set the default value you provide)
+objectPath.ensureExists(obj, "a.k.1", "DEFAULT");
+var oldVal = objectPath.ensureExists(obj, "a.b", "DEFAULT"); // oldval === "d"
+
+//deletes a path
+objectPath.del(obj, "a.b"); // obj.a.b is now undefined
+objectPath.del(obj, ["a","c",0]); // obj.a.c is now ['f']
+
+//tests path existence
+objectPath.has(obj, "a.b"); // true
+objectPath.has(obj, ["a","d"]); // false
+
+//bind object
+var model = objectPath({
+  a: {
+    b: "d",
+    c: ["e", "f"]
+  }
+});
+
+//now any method from above is supported directly w/o passing an object
+model.get("a.b");  //returns "d"
+model.get(["a.c.b"], "DEFAULT");  //returns "DEFAULT"
+model.del("a.b"); // obj.a.b is now undefined
+model.has("a.b"); // false
+
+```
+### How `object-path` deals with inherited properties
+
+By default `object-path` will only access an object's own properties. Look at the following example:
+
+```javascript
+var proto = {
+  notOwn: {prop: 'a'}
+}
+var obj = Object.create(proto);
+
+//This will return undefined (or the default value you specified), because notOwn is
+//an inherited property
+objectPath.get(obj, 'notOwn.prop');
+
+//This will set the property on the obj instance and not the prototype.
+//In other words proto.notOwn.prop === 'a' and obj.notOwn.prop === 'b'
+objectPath.set(obj, 'notOwn.prop', 'b');
+```
+To configure `object-path` to also deal with inherited properties, you need to create a new instance and specify
+the `includeInheritedProps = true` in the options object:
+
+```javascript
+var objectPath = require("object-path");
+var objectPathWithInheritedProps = objectPath.create({includeInheritedProps: true})
+```
+
+Alternatively, `object-path` exposes an instance already configured to handle inherited properties (`objectPath.withInheritedProps`):
+```javascript
+var objectPath = require("object-path");
+var objectPathWithInheritedProps = objectPath.withInheritedProps
+```
+
+Once you have the new instance, you can access inherited properties as you access other properties:
+```javascript
+var proto = {
+  notOwn: {prop: 'a'}
+}
+var obj = Object.create(proto);
+
+//This will return 'a'
+objectPath.withInheritedProps.get(obj, 'notOwn.prop');
+
+//This will set proto.notOwn.prop to 'b'
+objectPath.set(obj, 'notOwn.prop', 'b');
+```
+
+### Immutability
+
+If you are looking for an *immutable* alternative of this library, you can take a look at: [object-path-immutable](https://github.com/mariocasciaro/object-path-immutable)
+
+
+### Credits
+
+* [Mario Casciaro](https://github.com/mariocasciaro) - Author
+* [Paulo Cesar](https://github.com/pocesar) - Major contributor
diff --git a/benchmark.js b/benchmark.js
new file mode 100644
index 0000000..b447352
--- /dev/null
+++ b/benchmark.js
@@ -0,0 +1,52 @@
+var Benchpress = require('@mariocasciaro/benchpress')
+var benchmark = new Benchpress()
+var op = require('./')
+
+var testObj = {
+  level1_a: {
+    level2_a: {
+      level3_a: {
+        level4_a: {
+        }
+      }
+    }
+  }
+}
+
+var testObj2
+
+benchmark
+  .add('get existing', {
+    iterations: 100000,
+    fn: function() {
+      op.get(testObj, ['level1_a', 'level2_a', 'level3_a', 'level4_a'])
+    }
+  })
+  .add('get non-existing', {
+    iterations: 100000,
+    fn: function() {
+      op.get(testObj, ['level5_a'])
+    }
+  })
+  .add('push', {
+    iterations: 100000,
+    fn: function() {
+      op.push(testObj, ['level1_a', 'level2_a', 'level3_a', 'level4_a', 'level5_a'], 'val')
+    }
+  })
+  .add('set non existing', {
+    iterations: 100000,
+    fn: function() {
+      op.set(testObj2, ['level1_a', 'level2_b', 'level3_b', 'level4_b', 'level5_b'], 'val')
+    },
+    beforeEach: function() {
+      testObj2 = {}
+    }
+  })
+  .add('set existing', {
+    iterations: 100000,
+    fn: function() {
+      op.set(testObj, ['level1_a', 'level2_a', 'level3_a', 'level4_a', 'level5_b'], 'val')
+    }
+  })
+  .run()
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..5d76dce
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,16 @@
+{
+  "name": "object-path",
+  "main": "index.js",
+  "keywords": [
+    "deep",
+    "path",
+    "access",
+    "bean",
+    "object"
+  ],
+  "ignore" : [
+    "test.js",
+    "coverage",
+    "*.yml"
+  ]
+}
diff --git a/component.json b/component.json
new file mode 100644
index 0000000..115cf56
--- /dev/null
+++ b/component.json
@@ -0,0 +1,22 @@
+{
+  "name": "object-path",
+  "description": "Access deep properties using a path",
+  "version": "0.9.2",
+  "author": {
+    "name": "Mario Casciaro"
+  },
+  "homepage": "https://github.com/mariocasciaro/object-path",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mariocasciaro/object-path.git"
+  },
+  "main": "index.js",
+  "scripts": ["index.js"],
+  "keywords": [
+    "deep",
+    "path",
+    "access",
+    "bean"
+  ],
+  "license": "MIT"
+}
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..12b3b3b
--- /dev/null
+++ b/index.js
@@ -0,0 +1,291 @@
+(function (root, factory){
+  'use strict';
+
+  /*istanbul ignore next:cant test*/
+  if (typeof module === 'object' && typeof module.exports === 'object') {
+    module.exports = factory();
+  } else if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module.
+    define([], factory);
+  } else {
+    // Browser globals
+    root.objectPath = factory();
+  }
+})(this, function(){
+  'use strict';
+
+  var toStr = Object.prototype.toString;
+  function hasOwnProperty(obj, prop) {
+    if(obj == null) {
+      return false
+    }
+    //to handle objects with null prototypes (too edge case?)
+    return Object.prototype.hasOwnProperty.call(obj, prop)
+  }
+
+  function isEmpty(value){
+    if (!value) {
+      return true;
+    }
+    if (isArray(value) && value.length === 0) {
+        return true;
+    } else if (typeof value !== 'string') {
+        for (var i in value) {
+            if (hasOwnProperty(value, i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    return false;
+  }
+
+  function toString(type){
+    return toStr.call(type);
+  }
+
+  function isObject(obj){
+    return typeof obj === 'object' && toString(obj) === "[object Object]";
+  }
+
+  var isArray = Array.isArray || function(obj){
+    /*istanbul ignore next:cant test*/
+    return toStr.call(obj) === '[object Array]';
+  }
+
+  function isBoolean(obj){
+    return typeof obj === 'boolean' || toString(obj) === '[object Boolean]';
+  }
+
+  function getKey(key){
+    var intKey = parseInt(key);
+    if (intKey.toString() === key) {
+      return intKey;
+    }
+    return key;
+  }
+
+  function factory(options) {
+    options = options || {}
+
+    var objectPath = function(obj) {
+      return Object.keys(objectPath).reduce(function(proxy, prop) {
+        if(prop === 'create') {
+          return proxy;
+        }
+
+        /*istanbul ignore else*/
+        if (typeof objectPath[prop] === 'function') {
+          proxy[prop] = objectPath[prop].bind(objectPath, obj);
+        }
+
+        return proxy;
+      }, {});
+    };
+
+    function getShallowProperty(obj, prop) {
+      if (options.includeInheritedProps || (typeof prop === 'number' && Array.isArray(obj)) || hasOwnProperty(obj, prop)) {
+        return obj[prop];
+      }
+    }
+
+    function set(obj, path, value, doNotReplace){
+      if (typeof path === 'number') {
+        path = [path];
+      }
+      if (!path || path.length === 0) {
+        return obj;
+      }
+      if (typeof path === 'string') {
+        return set(obj, path.split('.').map(getKey), value, doNotReplace);
+      }
+      var currentPath = path[0];
+      var currentValue = getShallowProperty(obj, currentPath);
+      if (path.length === 1) {
+        if (currentValue === void 0 || !doNotReplace) {
+          obj[currentPath] = value;
+        }
+        return currentValue;
+      }
+
+      if (currentValue === void 0) {
+        //check if we assume an array
+        if(typeof path[1] === 'number') {
+          obj[currentPath] = [];
+        } else {
+          obj[currentPath] = {};
+        }
+      }
+
+      return set(obj[currentPath], path.slice(1), value, doNotReplace);
+    }
+
+    objectPath.has = function (obj, path) {
+      if (typeof path === 'number') {
+        path = [path];
+      } else if (typeof path === 'string') {
+        path = path.split('.');
+      }
+
+      if (!path || path.length === 0) {
+        return !!obj;
+      }
+
+      for (var i = 0; i < path.length; i++) {
+        var j = getKey(path[i]);
+
+        if((typeof j === 'number' && isArray(obj) && j < obj.length) ||
+          (options.includeInheritedProps ? (j in Object(obj)) : hasOwnProperty(obj, j))) {
+          obj = obj[j];
+        } else {
+          return false;
+        }
+      }
+
+      return true;
+    };
+
+    objectPath.ensureExists = function (obj, path, value){
+      return set(obj, path, value, true);
+    };
+
+    objectPath.set = function (obj, path, value, doNotReplace){
+      return set(obj, path, value, doNotReplace);
+    };
+
+    objectPath.insert = function (obj, path, value, at){
+      var arr = objectPath.get(obj, path);
+      at = ~~at;
+      if (!isArray(arr)) {
+        arr = [];
+        objectPath.set(obj, path, arr);
+      }
+      arr.splice(at, 0, value);
+    };
+
+    objectPath.empty = function(obj, path) {
+      if (isEmpty(path)) {
+        return void 0;
+      }
+      if (obj == null) {
+        return void 0;
+      }
+
+      var value, i;
+      if (!(value = objectPath.get(obj, path))) {
+        return void 0;
+      }
+
+      if (typeof value === 'string') {
+        return objectPath.set(obj, path, '');
+      } else if (isBoolean(value)) {
+        return objectPath.set(obj, path, false);
+      } else if (typeof value === 'number') {
+        return objectPath.set(obj, path, 0);
+      } else if (isArray(value)) {
+        value.length = 0;
+      } else if (isObject(value)) {
+        for (i in value) {
+          if (hasOwnProperty(value, i)) {
+            delete value[i];
+          }
+        }
+      } else {
+        return objectPath.set(obj, path, null);
+      }
+    };
+
+    objectPath.push = function (obj, path /*, values */){
+      var arr = objectPath.get(obj, path);
+      if (!isArray(arr)) {
+        arr = [];
+        objectPath.set(obj, path, arr);
+      }
+
+      arr.push.apply(arr, Array.prototype.slice.call(arguments, 2));
+    };
+
+    objectPath.coalesce = function (obj, paths, defaultValue) {
+      var value;
+
+      for (var i = 0, len = paths.length; i < len; i++) {
+        if ((value = objectPath.get(obj, paths[i])) !== void 0) {
+          return value;
+        }
+      }
+
+      return defaultValue;
+    };
+
+    objectPath.get = function (obj, path, defaultValue){
+      if (typeof path === 'number') {
+        path = [path];
+      }
+      if (!path || path.length === 0) {
+        return obj;
+      }
+      if (obj == null) {
+        return defaultValue;
+      }
+      if (typeof path === 'string') {
+        return objectPath.get(obj, path.split('.'), defaultValue);
+      }
+
+      var currentPath = getKey(path[0]);
+      var nextObj = getShallowProperty(obj, currentPath)
+      if (nextObj === void 0) {
+        return defaultValue;
+      }
+
+      if (path.length === 1) {
+        return nextObj;
+      }
+
+      return objectPath.get(obj[currentPath], path.slice(1), defaultValue);
+    };
+
+    objectPath.del = function del(obj, path) {
+      if (typeof path === 'number') {
+        path = [path];
+      }
+
+      if (obj == null) {
+        return obj;
+      }
+
+      if (isEmpty(path)) {
+        return obj;
+      }
+      if(typeof path === 'string') {
+        return objectPath.del(obj, path.split('.'));
+      }
+
+      var currentPath = getKey(path[0]);
+      var currentVal = getShallowProperty(obj, currentPath);
+      if(currentVal == null) {
+        return currentVal;
+      }
+
+      if(path.length === 1) {
+        if (isArray(obj)) {
+          obj.splice(currentPath, 1);
+        } else {
+          delete obj[currentPath];
+        }
+      } else {
+        if (obj[currentPath] !== void 0) {
+          return objectPath.del(obj[currentPath], path.slice(1));
+        }
+      }
+
+      return obj;
+    }
+
+    return objectPath;
+  }
+
+  var mod = factory();
+  mod.create = factory;
+  mod.withInheritedProps = factory({includeInheritedProps: true})
+  return mod;
+});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..bc1b0f3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,45 @@
+{
+  "name": "object-path",
+  "description": "Access deep object properties using a path",
+  "version": "0.11.3",
+  "author": {
+    "name": "Mario Casciaro"
+  },
+  "homepage": "https://github.com/mariocasciaro/object-path",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mariocasciaro/object-path.git"
+  },
+  "engines": {
+    "node": ">=0.10.0"
+  },
+  "devDependencies": {
+    "@mariocasciaro/benchpress": "^0.1.3",
+    "chai": "^3.5.0",
+    "coveralls": "^2.11.2",
+    "istanbul": "^0.4.4",
+    "mocha": "^2.2.4",
+    "mocha-lcov-reporter": "^1.2.0"
+  },
+  "scripts": {
+    "test": "istanbul cover ./node_modules/mocha/bin/_mocha test.js --report html -- -R spec"
+  },
+  "keywords": [
+    "deep",
+    "path",
+    "access",
+    "bean",
+    "get",
+    "property",
+    "dot",
+    "prop",
+    "object",
+    "obj",
+    "notation",
+    "segment",
+    "value",
+    "nested",
+    "key"
+  ],
+  "license": "MIT"
+}
diff --git a/test.js b/test.js
new file mode 100644
index 0000000..4bb9edd
--- /dev/null
+++ b/test.js
@@ -0,0 +1,913 @@
+'use strict';
+var expect = require('chai').expect,
+  objectPath = require('./index.js');
+
+
+function getTestObj() {
+  return {
+    a: 'b',
+    b: {
+      c: [],
+      d: ['a', 'b'],
+      e: [{},{f: 'g'}],
+      f: 'i'
+    }
+  };
+}
+
+describe('get', function() {
+  it('should return the value using unicode key', function() {
+    var obj = {
+      '15\u00f8C': {
+        '3\u0111': 1
+      }
+    };
+    expect(objectPath.get(obj, '15\u00f8C.3\u0111')).to.be.equal(1);
+    expect(objectPath.get(obj, ['15\u00f8C','3\u0111'])).to.be.equal(1);
+  });
+
+  it('should return the value using dot in key', function() {
+    var obj = {
+      'a.b': {
+        'looks.like': 1
+      }
+    };
+    expect(objectPath.get(obj, 'a.b.looks.like')).to.be.equal(void 0);
+    expect(objectPath.get(obj, ['a.b','looks.like'])).to.be.equal(1);
+  });
+
+  it('should return the value under shallow object', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'a')).to.be.equal('b');
+    expect(objectPath.get(obj, ['a'])).to.be.equal('b');
+  });
+
+  it('should work with number path', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj.b.d, 0)).to.be.equal('a');
+    expect(objectPath.get(obj.b, 0)).to.be.equal(void 0);
+  });
+
+  it('should return the value under deep object', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'b.f')).to.be.equal('i');
+    expect(objectPath.get(obj, ['b','f'])).to.be.equal('i');
+  });
+
+  it('should return the value under array', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'b.d.0')).to.be.equal('a');
+    expect(objectPath.get(obj, ['b','d',0])).to.be.equal('a');
+  });
+
+  it('should return the value under array deep', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'b.e.1.f')).to.be.equal('g');
+    expect(objectPath.get(obj, ['b','e',1,'f'])).to.be.equal('g');
+  });
+
+  it('should return undefined for missing values under object', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'a.b')).to.not.exist;
+    expect(objectPath.get(obj, ['a','b'])).to.not.exist;
+  });
+
+  it('should return undefined for missing values under array', function() {
+    var obj = getTestObj();
+    expect(objectPath.get(obj, 'b.d.5')).to.not.exist;
+    expect(objectPath.get(obj, ['b','d','5'])).to.not.exist;
+  });
+
+  it('should return the value under integer-like key', function() {
+    var obj = { '1a': 'foo' };
+    expect(objectPath.get(obj, '1a')).to.be.equal('foo');
+    expect(objectPath.get(obj, ['1a'])).to.be.equal('foo');
+  });
+
+  it('should return the default value when the key doesnt exist', function() {
+    var obj = { '1a': 'foo' };
+    expect(objectPath.get(obj, '1b', null)).to.be.equal(null);
+    expect(objectPath.get(obj, ['1b'], null)).to.be.equal(null);
+  });
+
+  it('should return the default value when path is empty', function() {
+    var obj = { '1a': 'foo' };
+    expect(objectPath.get(obj, '', null)).to.be.deep.equal({ '1a': 'foo' });
+    expect(objectPath.get(obj, [])).to.be.deep.equal({ '1a': 'foo' });
+    expect(objectPath.get({  }, ['1'])).to.be.equal(undefined);
+  });
+
+  it('should return the default value when object is null or undefined', function() {
+    expect(objectPath.get(null, 'test', 'a')).to.be.deep.equal('a');
+    expect(objectPath.get(undefined, 'test', 'a')).to.be.deep.equal('a');
+  });
+
+  it(
+    'should not fail on an object with a null prototype',
+    function assertSuccessForObjWithNullProto(){
+      var foo = 'FOO';
+      var objWithNullProto = Object.create(null);
+      objWithNullProto.foo = foo;
+      expect(objectPath.get(objWithNullProto, 'foo')).to.equal(foo);
+    }
+  );
+
+  it('should skip non own properties', function() {
+    var Base = function(enabled){ };
+    Base.prototype = {
+      one: {
+        two: true
+      }
+    };
+    var Extended = function(){
+      Base.call(this,  true);
+    };
+    Extended.prototype = Object.create(Base.prototype);
+
+    var extended = new Extended();
+
+    expect(objectPath.get(extended, ['one','two'])).to.be.equal(undefined);
+    extended.enabled = true;
+
+    expect(objectPath.get(extended, 'enabled')).to.be.equal(true);
+    expect(objectPath.get(extended, 'one')).to.be.equal(undefined);
+  });
+});
+
+
+describe('set', function() {
+  it('should set the value using unicode key', function() {
+    var obj = {
+      '15\u00f8C': {
+        '3\u0111': 1
+      }
+    };
+    objectPath.set(obj, '15\u00f8C.3\u0111', 2);
+    expect(objectPath.get(obj, '15\u00f8C.3\u0111')).to.be.equal(2);
+    objectPath.set(obj, '15\u00f8C.3\u0111', 3);
+    expect(objectPath.get(obj, ['15\u00f8C','3\u0111'])).to.be.equal(3);
+  });
+
+  it('should set the value using dot in key', function() {
+    var obj = {
+      'a.b': {
+        'looks.like': 1
+      }
+    };
+    objectPath.set(obj, ['a.b','looks.like'], 2);
+    expect(objectPath.get(obj, ['a.b','looks.like'])).to.be.equal(2);
+  });
+
+  it('should set value under shallow object', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, 'c', {m: 'o'});
+    expect(obj).to.have.deep.property('c.m', 'o');
+    obj = getTestObj();
+    objectPath.set(obj, ['c'], {m: 'o'});
+    expect(obj).to.have.deep.property('c.m', 'o');
+  });
+
+  it('should set value using number path', function() {
+    var obj = getTestObj();
+    objectPath.set(obj.b.d, 0, 'o');
+    expect(obj).to.have.deep.property('b.d.0', 'o');
+  });
+
+  it('should set value under deep object', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, 'b.c', 'o');
+    expect(obj).to.have.deep.property('b.c', 'o');
+    obj = getTestObj();
+    objectPath.set(obj, ['b','c'], 'o');
+    expect(obj).to.have.deep.property('b.c', 'o');
+  });
+
+  it('should set value under array', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, 'b.e.1.g', 'f');
+    expect(obj).to.have.deep.property('b.e.1.g', 'f');
+    obj = getTestObj();
+    objectPath.set(obj, ['b','e',1,'g'], 'f');
+    expect(obj).to.have.deep.property('b.e.1.g', 'f');
+
+    obj = {}
+    objectPath.set(obj, 'b.0', 'a');
+    objectPath.set(obj, 'b.1', 'b');
+    expect(obj.b).to.be.deep.equal(['a', 'b']);
+  });
+
+  it('should create intermediate objects', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, 'c.d.e.f', 'l');
+    expect(obj).to.have.deep.property('c.d.e.f', 'l');
+    obj = getTestObj();
+    objectPath.set(obj, ['c','d','e','f'], 'l');
+    expect(obj).to.have.deep.property('c.d.e.f', 'l');
+  });
+
+  it('should create intermediate arrays', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, 'c.0.1.m', 'l');
+    expect(obj.c).to.be.an('array');
+    expect(obj.c[0]).to.be.an('array');
+    expect(obj).to.have.deep.property('c.0.1.m', 'l');
+    obj = getTestObj();
+    objectPath.set(obj, ['c','0', 1,'m'], 'l');
+    expect(obj.c).to.be.an('object');
+    expect(obj.c[0]).to.be.an('array');
+    expect(obj).to.have.deep.property('c.0.1.m', 'l');
+  });
+
+  it('should set value under integer-like key', function() {
+    var obj = getTestObj();
+    objectPath.set(obj, '1a', 'foo');
+    expect(obj).to.have.deep.property('1a', 'foo');
+    obj = getTestObj();
+    objectPath.set(obj, ['1a'], 'foo');
+    expect(obj).to.have.deep.property('1a', 'foo');
+  });
+
+  it('should set value under empty array', function() {
+    var obj = [];
+    objectPath.set(obj, [0], 'foo');
+    expect(obj[0]).to.be.equal('foo');
+    obj = [];
+    objectPath.set(obj, '0', 'foo');
+    expect(obj[0]).to.be.equal('foo');
+  });
+});
+
+
+describe('push', function() {
+  it('should push value to existing array using unicode key', function() {
+    var obj = getTestObj();
+    objectPath.push(obj, 'b.\u1290c', 'l');
+    expect(obj).to.have.deep.property('b.\u1290c.0', 'l');
+    objectPath.push(obj, ['b','\u1290c'], 'l');
+    expect(obj).to.have.deep.property('b.\u1290c.1', 'l');
+  });
+
+  it('should push value to existing array using dot key', function() {
+    var obj = getTestObj();
+    objectPath.push(obj, ['b','z.d'], 'l');
+    expect(objectPath.get(obj, ['b','z.d', 0])).to.be.equal('l');
+  });
+
+  it('should push value to existing array', function() {
+    var obj = getTestObj();
+    objectPath.push(obj, 'b.c', 'l');
+    expect(obj).to.have.deep.property('b.c.0', 'l');
+    obj = getTestObj();
+    objectPath.push(obj, ['b','c'], 'l');
+    expect(obj).to.have.deep.property('b.c.0', 'l');
+  });
+
+  it('should push value to new array', function() {
+    var obj = getTestObj();
+    objectPath.push(obj, 'b.h', 'l');
+    expect(obj).to.have.deep.property('b.h.0', 'l');
+    obj = getTestObj();
+    objectPath.push(obj, ['b','h'], 'l');
+    expect(obj).to.have.deep.property('b.h.0', 'l');
+  });
+
+  it('should push value to existing array using number path', function() {
+    var obj = getTestObj();
+    objectPath.push(obj.b.e, 0, 'l');
+    expect(obj).to.have.deep.property('b.e.0.0', 'l');
+  });
+
+});
+
+
+describe('ensureExists', function() {
+  it('should create the path if it does not exists', function() {
+    var obj = getTestObj();
+    var oldVal = objectPath.ensureExists(obj, 'b.g.1.l', 'test');
+    expect(oldVal).to.not.exist;
+    expect(obj).to.have.deep.property('b.g.1.l', 'test');
+    oldVal = objectPath.ensureExists(obj, 'b.g.1.l', 'test1');
+    expect(oldVal).to.be.equal('test');
+    expect(obj).to.have.deep.property('b.g.1.l', 'test');
+    oldVal = objectPath.ensureExists(obj, 'b.\u8210', 'ok');
+    expect(oldVal).to.not.exist;
+    expect(obj).to.have.deep.property('b.\u8210', 'ok');
+    oldVal = objectPath.ensureExists(obj, ['b','dot.dot'], 'ok');
+    expect(oldVal).to.not.exist;
+    expect(objectPath.get(obj, ['b','dot.dot'])).to.be.equal('ok');
+  });
+
+
+  it('should return the object if path is empty', function() {
+    var obj = getTestObj();
+    expect(objectPath.ensureExists(obj, [], 'test')).to.have.property('a', 'b');
+  });
+
+  it('Issue #26', function() {
+    var any = {};
+    objectPath.ensureExists(any, ['1','1'], {});
+    expect(any).to.be.an('object');
+    expect(any[1]).to.be.an('object');
+    expect(any[1][1]).to.be.an('object');
+  });
+});
+
+describe('coalesce', function(){
+  it('should return the first non-undefined value', function(){
+    var obj = {
+      should: {have: 'prop'}
+    };
+
+    expect(objectPath.coalesce(obj, [
+      'doesnt.exist',
+      ['might','not','exist'],
+      'should.have'
+    ])).to.equal('prop');
+  });
+
+  it('should work with falsy values (null, 0, \'\', false)', function(){
+    var obj = {
+      is: {
+        false: false,
+        null: null,
+        empty: '',
+        zero: 0
+      }
+    };
+
+    expect(objectPath.coalesce(obj, [
+      'doesnt.exist',
+      'is.zero'
+    ])).to.equal(0);
+
+    expect(objectPath.coalesce(obj, [
+      'doesnt.exist',
+      'is.false'
+    ])).to.equal(false);
+
+    expect(objectPath.coalesce(obj, [
+      'doesnt.exist',
+      'is.null'
+    ])).to.equal(null);
+
+    expect(objectPath.coalesce(obj, [
+      'doesnt.exist',
+      'is.empty'
+    ])).to.equal('');
+  });
+
+  it('returns defaultValue if no paths found', function(){
+    var obj = {
+      doesnt: 'matter'
+    };
+
+    expect(objectPath.coalesce(obj, ['some.inexistant','path',['on','object']], 'false')).to.equal('false');
+  });
+
+  it('works with unicode and dot keys', function(){
+    var obj = {
+      '\u7591': true,
+      'dot.dot': false
+    };
+
+    expect(objectPath.coalesce(obj, ['1', '\u7591', 'a.b'])).to.equal(true);
+    expect(objectPath.coalesce(obj, ['1', ['dot.dot'], '\u7591'])).to.equal(false);
+  });
+});
+
+describe('empty', function(){
+  it('should ignore invalid arguments safely', function(){
+    var obj = {};
+    expect(objectPath.empty()).to.equal(void 0);
+    expect(objectPath.empty(obj, 'path')).to.equal(void 0);
+    expect(objectPath.empty(obj, '')).to.equal(void 0);
+
+    obj.path = true;
+
+    expect(objectPath.empty(obj, 'inexistant')).to.equal(void 0);
+  });
+
+  it('should empty each path according to their types', function(){
+    function Instance(){
+      this.notOwn = true;
+    }
+
+    /*istanbul ignore next: not part of code */
+    Instance.prototype.test = function(){};
+    /*istanbul ignore next: not part of code */
+    Instance.prototype.arr = [];
+
+    var
+      obj = {
+        string: 'some string',
+        array: ['some','array',[1,2,3]],
+        number: 21,
+        boolean: true,
+        object: {
+          some:'property',
+          sub: {
+            'property': true
+          }
+        },
+        instance: new Instance()
+      };
+
+    /*istanbul ignore next: not part of code */
+    obj['function'] = function(){};
+
+    objectPath.empty(obj, ['array','2']);
+    expect(obj.array[2]).to.deep.equal([]);
+
+    objectPath.empty(obj, 'object.sub');
+    expect(obj.object.sub).to.deep.equal({});
+
+    objectPath.empty(obj, 'instance.test');
+    //instance.test is not own property, so it shouldn't be emptied
+    expect(obj.instance.test).to.be.a('function');
+    expect(Instance.prototype.test).to.be.a('function');
+
+    objectPath.empty(obj, 'string');
+    objectPath.empty(obj, 'number');
+    objectPath.empty(obj, 'boolean');
+    objectPath.empty(obj, 'function');
+    objectPath.empty(obj, 'array');
+    objectPath.empty(obj, 'object');
+    objectPath.empty(obj, 'instance');
+
+    expect(obj.string).to.equal('');
+    expect(obj.array).to.deep.equal([]);
+    expect(obj.number).to.equal(0);
+    expect(obj.boolean).to.equal(false);
+    expect(obj.object).to.deep.equal({});
+    expect(obj.instance.notOwn).to.be.an('undefined');
+    expect(obj.instance.arr).to.be.an('array');
+    expect(obj['function']).to.equal(null);
+  });
+});
+
+describe('del', function(){
+  it('should work with number path', function(){
+    var obj = getTestObj();
+    objectPath.del(obj.b.d, 1);
+    expect(obj.b.d).to.deep.equal(['a']);
+  });
+
+  it('should delete deep paths', function(){
+    var obj = getTestObj();
+
+    expect(objectPath.del(obj)).to.be.equal(obj);
+
+    objectPath.set(obj, 'b.g.1.0', 'test');
+    objectPath.set(obj, 'b.g.1.1', 'test');
+    objectPath.set(obj, 'b.h.az', 'test');
+    objectPath.set(obj, 'b.\ubeef', 'test');
+    objectPath.set(obj, ['b','dot.dot'], 'test');
+
+    expect(obj).to.have.deep.property('b.g.1.0','test');
+    expect(obj).to.have.deep.property('b.g.1.1','test');
+    expect(obj).to.have.deep.property('b.h.az','test');
+    expect(obj).to.have.deep.property('b.\ubeef','test');
+
+    objectPath.del(obj, 'b.h.az');
+    expect(obj).to.not.have.deep.property('b.h.az');
+    expect(obj).to.have.deep.property('b.h');
+
+    objectPath.del(obj, 'b.g.1.1');
+    expect(obj).to.not.have.deep.property('b.g.1.1');
+    expect(obj).to.have.deep.property('b.g.1.0','test');
+
+    objectPath.del(obj, 'b.\ubeef');
+    expect(obj).to.not.have.deep.property('b.\ubeef');
+
+    objectPath.del(obj, ['b','dot.dot']);
+    expect(objectPath.get(obj, ['b','dot.dot'])).to.be.equal(void 0);
+
+    objectPath.del(obj, ['b','g','1','0']);
+    expect(obj).to.not.have.deep.property('b.g.1.0');
+    expect(obj).to.have.deep.property('b.g.1');
+
+    expect(objectPath.del(obj, ['b'])).to.not.have.deep.property('b.g');
+    expect(obj).to.be.deep.equal({'a':'b'});
+  });
+
+  it('should remove items from existing array', function(){
+    var obj = getTestObj();
+
+    objectPath.del(obj, 'b.d.0');
+    expect(obj.b.d).to.have.length(1);
+    expect(obj.b.d).to.be.deep.equal(['b']);
+
+    objectPath.del(obj, 'b.d.0');
+    expect(obj.b.d).to.have.length(0);
+    expect(obj.b.d).to.be.deep.equal([]);
+  });
+});
+
+describe('insert', function(){
+  it('should insert value into existing array', function(){
+    var obj = getTestObj();
+
+    objectPath.insert(obj, 'b.c', 'asdf');
+    expect(obj).to.have.deep.property('b.c.0', 'asdf');
+    expect(obj).to.not.have.deep.property('b.c.1');
+  });
+
+  it('should create intermediary array', function(){
+    var obj = getTestObj();
+
+    objectPath.insert(obj, 'b.c.0', 'asdf');
+    expect(obj).to.have.deep.property('b.c.0.0', 'asdf');
+  });
+
+  it('should insert in another index', function(){
+    var obj = getTestObj();
+
+    objectPath.insert(obj, 'b.d', 'asdf', 1);
+    expect(obj).to.have.deep.property('b.d.1', 'asdf');
+    expect(obj).to.have.deep.property('b.d.0', 'a');
+    expect(obj).to.have.deep.property('b.d.2', 'b');
+  });
+
+  it('should handle sparse array', function(){
+    var obj = getTestObj();
+    obj.b.d = new Array(4);
+    obj.b.d[0] = 'a';
+    obj.b.d[1] = 'b';
+
+    objectPath.insert(obj, 'b.d', 'asdf', 3);
+    expect(obj.b.d).to.have.members([
+      'a',
+      'b',
+      ,
+      ,
+      'asdf'
+    ]);
+  });
+});
+
+describe('has', function () {
+  it('should return false for empty object', function () {
+    expect(objectPath.has({}, 'a')).to.be.equal(false);
+  });
+
+  it('should handle empty paths properly', function () {
+    var obj = getTestObj();
+    expect(objectPath.has(obj, '')).to.be.equal(false);
+    expect(objectPath.has(obj, [''])).to.be.equal(false);
+    obj[''] = 1
+    expect(objectPath.has(obj, '')).to.be.equal(true);
+    expect(objectPath.has(obj, [''])).to.be.equal(true);
+
+    expect(objectPath.has(obj, [])).to.be.equal(true);
+    expect(objectPath.has(null, [])).to.be.equal(false);
+  });
+
+  it('should test under shallow object', function() {
+    var obj = getTestObj();
+    expect(objectPath.has(obj, 'a')).to.be.equal(true);
+    expect(objectPath.has(obj, ['a'])).to.be.equal(true);
+    expect(objectPath.has(obj, 'z')).to.be.equal(false);
+    expect(objectPath.has(obj, ['z'])).to.be.equal(false);
+  });
+
+  it('should work with number path', function() {
+    var obj = getTestObj();
+    expect(objectPath.has(obj.b.d, 0)).to.be.equal(true);
+    expect(objectPath.has(obj.b, 0)).to.be.equal(false);
+    expect(objectPath.has(obj.b.d, 10)).to.be.equal(false);
+    expect(objectPath.has(obj.b, 10)).to.be.equal(false);
+  });
+
+  it('should test under deep object', function() {
+    var obj = getTestObj();
+    expect(objectPath.has(obj, 'b.f')).to.be.equal(true);
+    expect(objectPath.has(obj, ['b','f'])).to.be.equal(true);
+    expect(objectPath.has(obj, 'b.g')).to.be.equal(false);
+    expect(objectPath.has(obj, ['b','g'])).to.be.equal(false);
+  });
+
+  it('should test value under array', function() {
+    var obj = {
+      b: ['a']
+    };
+    obj.b[3] = {o: 'a'}
+    expect(objectPath.has(obj, 'b.0')).to.be.equal(true);
+    expect(objectPath.has(obj, 'b.1')).to.be.equal(true);
+    expect(objectPath.has(obj, 'b.3.o')).to.be.equal(true);
+    expect(objectPath.has(obj, 'b.3.qwe')).to.be.equal(false);
+    expect(objectPath.has(obj, 'b.4')).to.be.equal(false);
+  });
+
+  it('should test the value under array deep', function() {
+    var obj = getTestObj();
+    expect(objectPath.has(obj, 'b.e.1.f')).to.be.equal(true);
+    expect(objectPath.has(obj, ['b','e',1,'f'])).to.be.equal(true);
+    expect(objectPath.has(obj, 'b.e.1.f.g.h.i')).to.be.equal(false);
+    expect(objectPath.has(obj, ['b','e',1,'f','g','h','i'])).to.be.equal(false);
+  });
+
+  it('should test the value under integer-like key', function() {
+    var obj = { '1a': 'foo' };
+    expect(objectPath.has(obj, '1a')).to.be.equal(true);
+    expect(objectPath.has(obj, ['1a'])).to.be.equal(true);
+  });
+
+  it('should distinct nonexistent key and key = undefined', function() {
+    var obj = {};
+    expect(objectPath.has(obj, 'key')).to.be.equal(false);
+
+    obj.key = undefined;
+    expect(objectPath.has(obj, 'key')).to.be.equal(true);
+  });
+
+  it('should work with deep undefined/null values', function() {
+    var obj = {};
+    expect(objectPath.has(obj, 'missing.test')).to.be.equal(false);
+
+    obj.missing = null;
+    expect(objectPath.has(obj, 'missing.test')).to.be.equal(false);
+
+    obj.sparseArray = [1, undefined, 3]
+    expect(objectPath.has(obj, 'sparseArray.1.test')).to.be.equal(false);
+  });
+});
+
+
+
+describe('bind object', function () {
+  // just get one scenario from each feature, so whole functionality is proxied well
+  it('should return the value under shallow object', function() {
+    var obj = getTestObj();
+    var model = objectPath(obj);
+    expect(model.get('a')).to.be.equal('b');
+    expect(model.get(['a'])).to.be.equal('b');
+  });
+
+  it('should set value under shallow object', function() {
+    var obj = getTestObj();
+    var model = objectPath(obj);
+    model.set('c', {m: 'o'});
+    expect(obj).to.have.deep.property('c.m', 'o');
+    obj = getTestObj();
+    model = objectPath(obj);
+    model.set(['c'], {m: 'o'});
+    expect(obj).to.have.deep.property('c.m', 'o');
+  });
+
+  it('should push value to existing array', function() {
+    var obj = getTestObj();
+    var model = objectPath(obj);
+    model.push('b.c', 'l');
+    expect(obj).to.have.deep.property('b.c.0', 'l');
+    obj = getTestObj();
+    model = objectPath(obj);
+    model.push(['b','c'], 'l');
+    expect(obj).to.have.deep.property('b.c.0', 'l');
+  });
+
+  it('should create the path if it does not exists', function() {
+    var obj = getTestObj();
+    var model = objectPath(obj);
+    var oldVal = model.ensureExists('b.g.1.l', 'test');
+    expect(oldVal).to.not.exist;
+    expect(obj).to.have.deep.property('b.g.1.l', 'test');
+    oldVal = model.ensureExists('b.g.1.l', 'test1');
+    expect(oldVal).to.be.equal('test');
+    expect(obj).to.have.deep.property('b.g.1.l', 'test');
+  });
+
+  it('should return the first non-undefined value', function(){
+    var obj = {
+      should: {have: 'prop'}
+    };
+    var model = objectPath(obj);
+
+    expect(model.coalesce([
+      'doesnt.exist',
+      ['might','not','exist'],
+      'should.have'
+    ])).to.equal('prop');
+  });
+
+  it('should empty each path according to their types', function(){
+    function Instance(){
+      this.notOwn = true;
+    }
+
+    /*istanbul ignore next: not part of code */
+    Instance.prototype.test = function(){};
+    /*istanbul ignore next: not part of code */
+    Instance.prototype.arr = [];
+
+    var
+      obj = {
+        string: 'some string',
+        array: ['some','array',[1,2,3]],
+        number: 21,
+        boolean: true,
+        object: {
+          some:'property',
+          sub: {
+            'property': true
+          }
+        },
+        instance: new Instance()
+      };
+
+    /*istanbul ignore next: not part of code */
+    obj['function'] = function(){};
+
+    var model = objectPath(obj);
+
+    model.empty(['array','2']);
+    expect(obj.array[2]).to.deep.equal([]);
+
+    model.empty('object.sub');
+    expect(obj.object.sub).to.deep.equal({});
+
+    model.empty('instance.test');
+    //instance.test is not own property so it shouldn't be emptied
+    expect(obj.instance.test).to.be.a('function');
+    expect(Instance.prototype.test).to.be.a('function');
+
+    model.empty('string');
+    model.empty('number');
+    model.empty('boolean');
+    model.empty('function');
+    model.empty('array');
+    model.empty('object');
+    model.empty('instance');
+
+    expect(obj.string).to.equal('');
+    expect(obj.array).to.deep.equal([]);
+    expect(obj.number).to.equal(0);
+    expect(obj.boolean).to.equal(false);
+    expect(obj.object).to.deep.equal({});
+    expect(obj.instance.notOwn).to.be.an('undefined');
+    expect(obj.instance.arr).to.be.an('array');
+    expect(obj['function']).to.equal(null);
+  });
+
+  it('should delete deep paths', function(){
+    var obj = getTestObj();
+    var model = objectPath(obj);
+
+    expect(model.del()).to.be.equal(obj);
+
+    model.set('b.g.1.0', 'test');
+    model.set('b.g.1.1', 'test');
+    model.set('b.h.az', 'test');
+
+    expect(obj).to.have.deep.property('b.g.1.0','test');
+    expect(obj).to.have.deep.property('b.g.1.1','test');
+    expect(obj).to.have.deep.property('b.h.az','test');
+
+    model.del('b.h.az');
+    expect(obj).to.not.have.deep.property('b.h.az');
+    expect(obj).to.have.deep.property('b.h');
+
+    model.del('b.g.1.1');
+    expect(obj).to.not.have.deep.property('b.g.1.1');
+    expect(obj).to.have.deep.property('b.g.1.0','test');
+
+    model.del(['b','g','1','0']);
+    expect(obj).to.not.have.deep.property('b.g.1.0');
+    expect(obj).to.have.deep.property('b.g.1');
+
+    expect(model.del(['b'])).to.not.have.deep.property('b.g');
+    expect(obj).to.be.deep.equal({'a':'b'});
+  });
+
+  it('should insert value into existing array', function(){
+    var obj = getTestObj();
+    var model = objectPath(obj);
+
+    model.insert('b.c', 'asdf');
+    expect(obj).to.have.deep.property('b.c.0', 'asdf');
+    expect(obj).to.not.have.deep.property('b.c.1');
+  });
+
+  it('should test under shallow object', function() {
+    var obj = getTestObj();
+    var model = objectPath(obj);
+
+    expect(model.has('a')).to.be.equal(true);
+    expect(model.has(['a'])).to.be.equal(true);
+    expect(model.has('z')).to.be.equal(false);
+    expect(model.has(['z'])).to.be.equal(false);
+  });
+});
+
+describe('Don\'t access not own properties [default]', function () {
+  it('should not get a not own property', function() {
+    var Obj = function() {};
+    Obj.prototype.notOwn = {a: 'a'};
+    var obj = new Obj();
+
+    expect(objectPath.get(obj, 'notOwn')).to.be.undefined
+  });
+
+  it('should set a not own property on the instance (not the prototype)', function() {
+    var proto = {
+      notOwn: {}
+    }
+    var obj = Object.create(proto)
+
+    objectPath.set(obj, 'notOwn.test', 'a');
+    expect(obj.notOwn.test).to.be.equal('a');
+    expect(proto.notOwn).to.be.deep.equal({});
+  });
+
+  it('has should return false on a not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto)
+
+
+    expect(objectPath.has(obj, 'notOwn')).to.be.false;
+    expect(objectPath.has(obj, 'notOwn.a')).to.be.false;
+  });
+
+  it('empty should not empty on a not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto);
+
+    objectPath.empty(obj, 'notOwn');
+    expect(proto.notOwn).to.be.deep.equal({a: 'a'});
+    expect(obj.notOwn).to.be.deep.equal({a: 'a'});
+  });
+
+  it('del should not delete not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto);
+
+    objectPath.del(obj, 'notOwn.a');
+    expect(proto.notOwn).to.be.deep.equal({a: 'a'});
+    //expect(obj.notOwn).to.be.deep.equal({a: 'a'});
+    //objectPath.del(obj, 'notOwn');
+    //expect(proto).to.be.deep.equal({notOwn: {a: 'a'}});
+    //expect(obj).to.be.deep.equal({notOwn: {a: 'a'}});
+  });
+});
+
+describe('Access own properties [optional]', function () {
+  it('should get a not own property', function() {
+    var Obj = function() {};
+    Obj.prototype.notOwn = {a: 'a'};
+    var obj = new Obj();
+
+    expect(objectPath.withInheritedProps.get(obj, 'notOwn.a')).to.be.equal('a')
+  });
+
+  it('should set a deep not own property on the prototype (if exists)', function() {
+    var proto = {
+      notOwn: {}
+    }
+    var obj = Object.create(proto)
+
+    objectPath.withInheritedProps.set(obj, 'notOwn.test', 'a');
+    expect(obj.notOwn.test).to.be.equal('a');
+    expect(proto.notOwn).to.be.deep.equal({test: 'a'});
+  });
+
+
+  it('has should return true on a not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto)
+
+    expect(objectPath.withInheritedProps.has(obj, 'notOwn')).to.be.true;
+    expect(objectPath.withInheritedProps.has(obj, 'notOwn.a')).to.be.true;
+  });
+
+  it('empty should empty a not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto);
+
+    objectPath.withInheritedProps.empty(obj, 'notOwn');
+    expect(proto.notOwn).to.be.deep.equal({});
+    expect(obj.notOwn).to.be.deep.equal({});
+  });
+
+  it('del should delete a not own property', function() {
+    var proto = {
+      notOwn: {a: 'a'}
+    }
+    var obj = Object.create(proto);
+
+    objectPath.withInheritedProps.del(obj, 'notOwn.a');
+    expect(proto.notOwn).to.be.deep.equal({});
+    //expect(obj.notOwn).to.be.deep.equal({});
+    objectPath.withInheritedProps.del(obj, 'notOwn');
+    //expect(proto).to.be.deep.equal({notOwn: {}});
+    //expect(obj).to.be.deep.equal({notOwn: {}});
+  });
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-object-path.git



More information about the Pkg-javascript-commits mailing list