Manual Reference Source Test

tests/objectarray.spec.js

import ObjectArray from 'index';
var beforeEach = window.beforeEach;
// var aftereach = window.afterEach;

/**
*  @test {ObjectArray#data}
*/
describe('Data getter and setter', function () {
  it('should get and set data', function () {
    let i = new ObjectArray();

    i.data = {test: 'fixture'};
    i.data.test.should.equal('fixture');
  });
});

/**
*  @test {ObjectArray#throwing}
*/
describe('Global throwing behaviour override', function () {
  it('should always throw an exception', function () {
    let i = new ObjectArray();

    i.throwing(true);
    expect(i.pull.bind(i, 'key')).to.throw(TypeError);
    expect(i.dataset.bind(i, 'key', undefined, false)).to.throw(TypeError);
  });

  it('should never throw an exception', function () {
    let i = new ObjectArray();

    i.throwing(false);
    expect(i.pull('key')).to.be.undefined;
    expect(i.dataset('key', undefined, false)).to.be.undefined;
  });
});

/**
*  @test {ObjectArray#pKey}
*/
describe('Parent key memorizer', function () {

  it('should use memorizer when using data read/write methods', function () {
    let i = new ObjectArray();

    i.pKey('test1');
    i.push('test11', 'fixture');
    i.pull('test11').should.equal('fixture');
    i._data.should.eql({test1: { test11: 'fixture'}});
  });

});

/**
*  @test {ObjectArray#_key}
*/
describe('Key constructor', function () {

  it('should return dotted key', function () {
    let i = new ObjectArray();

    i.push('test1.test21', 'fixture');
    i._key('test1').should.equal('test1');
    i._key('test21', 'test1').should.equal('test1.test21');
  });

  it('should return undefined', function () {
    let i = new ObjectArray();

    i.push('test1.test21', 'fixture');
    expect(i._key('test2', undefined, false)).to.be.undefined;
    expect(i._key('test22', 'test1', false)).to.be.undefined;
  });

  it('should throw exception', function () {
    let i = new ObjectArray();

    i.push('test1.test21', 'fixture');
    expect(i._key.bind(i, 'test2', undefined, true)).to.throw(TypeError);
    expect(i._key.bind(i, 'test22', 'test2', true)).to.throw(TypeError);
  });
});

/**
*  @test {ObjectArray#clone}
*  @test {ObjectArray#flatten}
*/
describe('Cloning ObjectArray', function () {

  it('should return a clone with empty data', function () {
    let i = new ObjectArray();

    i.clone().should.not.equal(i);
    i.clone().data.should.eql(i.data);
  });

  it('should return a clone with nested data', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    i.clone().should.not.equal(i);
    i.clone().data.should.eql(i.data);
  });

  it('should restore data in clone after flattening original', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    i.flatten().clone().should.not.equal(i);
    i.clone().data.should.eql(i.data);
  });

  it('should restore data in clone after dotted flattening original', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        test21: 0,
        test22: true
      }
    });

    i.flatten(true).clone(false).should.not.equal(i);
    i.clone(false).data.should.eql({
      test1: 'fixture',
      test2: {
        test21: 0,
        test22: true
      }
    });
  });
});

/**
*  @test {ObjectArray#empty}
*/
describe('Empty ObjectArray or remove subset', function () {
  let i;

  let data = {
    test1: 'fixture',
    test2: {
      test21: 0,
      test22: true
    }
  };

  beforeEach(function () {
    i = new ObjectArray(data);
  });

  it('should empty all data', function () {
    i.empty();
    i._data.should.eql({});
  });

  it('should empty subset', function () {
    i.empty('test2');
    i._data.should.eql({test1: 'fixture'});
  });

  it('should throw an exception if key missing', function () {
    expect(i.empty.bind(i, 'test3')).to.throw(TypeError);
  });

  it('should do nothing if key missing', function () {
    i.empty('test3', undefined, false);
    i._data.should.eql(data);
  });
});

/**
*  @test {ObjectArray#length}
*/
describe('Length', function () {
  let i = new ObjectArray();

  it('should returns length', function () {
    i.length().should.equal(0);
    i.push('test', 'fixture');
    i.length().should.equal(1);
    i.push('test2', 'fixture2');
    i.length().should.equal(2);
  });

  it('should throw an exception if key missing', function () {
    expect(i.length.bind(i, 'dat.wrong.path')).to.throw(TypeError);
  });

  it('should return undefined if key missing', function () {
    expect(i.length('dat.wrong.path', undefined, false)).to.be.undefined;
  });
});

describe('ObjectArray keys and values', function () {

  it('should returns keys', function () {
    let i = new ObjectArray();

    i.keys().should.eql([]);
    i.push('test', 'fixture');
    i.keys().should.eql(['test']);
    i.push('test2', 'fixture2');
    i.keys().should.eql(['test', 'test2']);
    expect(i.keys.bind(i, 'dat.wrong.path')).to.throw(TypeError);
  });

  it('should returns values', function () {
    let i = new ObjectArray();

    i.values().should.eql([]);
    i.push('test', 'fixture');
    i.values().should.eql(['fixture']);
    i.push('test2', 'fixture2');
    i.values().should.eql(['fixture', 'fixture2']);
    expect(i.values.bind(i, 'dat.wrong.path')).to.throw(TypeError);
    expect(i.values('dat.wrong.path', undefined, false)).to.eql([]);
  });
  it('should returns right keys and values for dotted object', function () {
    var i = new ObjectArray({
      dat: {
        long: {
          path: 'fixture1',
          dream: 'fixture2'
        }
      }
    });

    i.keys().should.eql(['dat']);
    i.values().should.eql([{long: {path: 'fixture1', dream: 'fixture2'}}]);
    i.keys('dat.long').should.eql(['path', 'dream']);
    i.values('dat.long').should.eql(['fixture1', 'fixture2']);
    expect(i.keys.bind(i, 'dat.short')).to.throw(TypeError);
    expect(i.values.bind(i, 'dat.short')).to.throw(TypeError);
  });
});

describe('Has key, data fetch and parent data fetch', function () {
  it('should find key', function () {
    let i = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    i.has('test').should.equal(true);
    i.has('test2').should.equal(true);
    i.has('test2.test21').should.equal(true);
    i.has('test2.test22').should.equal(true);
    i.has('test3').should.equal(false);
    i.has('test2.test23').should.equal(false);
  });

  it('should find data', function () {
    let i = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    i.dataset('test').should.equal('fixture');
    i.dataset('test2').should.eql({
      test21: 'fixture21',
      test22: 'fixture22'
    });
    i.dataset('test2.test21').should.equal('fixture21');
    i.dataset('test21', 'test2').should.equal('fixture21');
    expect(i.dataset(i, 'test3')).to.be.undefined;
    expect(i.dataset('test23', 'test2')).to.be.undefined;
    expect(i.dataset.bind(i, 'test3', undefined, true)).to.throw(TypeError);
    expect(i.dataset.bind(i, 'test23', 'test2', true)).to.throw(TypeError);
    i.throwing(false);
    expect(i.dataset('test3')).to.be.undefined;
    expect(i.dataset('test23', 'test2')).to.be.undefined;
    expect(i.dataset('test3', undefined, true)).to.be.undefined;
    expect(i.dataset('test23', 'test2', true)).to.be.undefined;
    i.throwing(true);
    expect(i.dataset.bind(i, 'test3')).to.throw(TypeError);
    expect(i.dataset.bind(i, 'test23', 'test2')).to.throw(TypeError);
    expect(i.dataset.bind(i, 'test3', undefined, false)).to.throw(TypeError);
    expect(i.dataset.bind(i, 'test23', 'test2', false)).to.throw(TypeError);
  });

  it('should find parent key', function () {
    let i = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    expect(i.parentKey('test')).to.equal(undefined);
    i.parentKey('test2.test21').should.equal('test2');
  });
});

describe('Check key/value', function () {
  it('Strict equality', function () {
    let i = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 0,
        test22: '0'
      }
    });

    i.check('test2.test21', 0).should.be.true;
    i.check('test2.test21', '0').should.be.false;
    i.check('test2.test21', 'fixture').should.be.false;
    i.check('test22', '0', 'test2').should.be.true;
    i.check('test22', 0, 'test2').should.be.false;
  });

  it('Loose equality', function () {
    let i = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 0,
        test22: '0'
      }
    });

    i.check('test2.test21', 0, '', false).should.be.true;
    i.check('test2.test21', '0', '', false).should.be.true;
    i.check('test22', '0', 'test2', false).should.be.true;
    i.check('test22', 0, 'test2', false).should.be.true;
    i.check('test2.test21', 'fixture', '', false).should.be.false;
  });
});

describe('Flatten ObjectArray', function () {
  it('should change nothing if data empty', function () {
    let i = new ObjectArray();

    i.flatten().should.eql(i);
    i.data.should.eql({});
  });

  it('should change nothing if data already flattened', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: 0
    });

    i.flatten().should.eql(i);
    i.data.should.eql({test1: 'fixture', test2: 0});
  });

  it('should flatten dataset', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        test21: 0,
        test22: true
      }
    });

    i.flatten().should.eql(i);
    i.data.should.eql({test1: 'fixture', test21: 0, test22: true});
  });

  it('should flatten dataset and replace', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        test1: 0,
        test2: true
      }
    });

    i.flatten().should.eql(i);
    i.data.should.eql({test1: 0, test2: true});
  });

  it('should flatten dataset and dot keys', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        test1: 0,
        test2: true
      }
    });

    i.flatten(true).should.eql(i);
    i.data.should.eql({test1: 'fixture', 'test2.test1': 0, 'test2.test2': true});
  });

  it('should flatten subdataset and no change', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        test21: 0,
        test22: true
      }
    });

    i.flatten(false, 'test2').should.eql(i);
    i.data.should.eql({test1: 'fixture', test2: {test21: 0, test22: true}});
  });

  it('should throw an exception if key does not exist', function () {
    let i = new ObjectArray();

    expect(i.flatten.bind(i, true, 'test3')).to.throw(TypeError);
  });

  it('should flatten subdataset', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    i.flatten(false, 'test2').should.eql(i);
    i.data.should.eql({test1: 'fixture', test2: {test2x: 0, test2y1: true, test2y2: 'fix'}});
  });

  it('should flatten subdataset and dot keys', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    i.flatten(true, 'test2').should.eql(i);
    i.data.should.eql({test1: 'fixture', test2: {'testx.test2x': 0, 'testy.test2y1': true, 'testy.test2y2': 'fix'}});
  });

});

describe('Data manipulation', function () {

  it('should create all needed keys', function () {
    let i = new ObjectArray();

    i.push('dat.really.long.path', 'fixture');
    i.data.should.eql({
      dat: {
        really: {
          long: {
            path: 'fixture'
          }
        }
      }
    });
  });

  it('should push or import ObjectArray without losing data', function () {
    let o = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    let i = new ObjectArray().push('itest', o);

    i.data.should.eql({itest: {
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    }});

    i = new ObjectArray().push('itest', o, 'dat.path');

    i.data.should.eql({dat: {path: {itest: {
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    }}}});

    i = new ObjectArray().import(o);

    i.data.should.eql({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    i = new ObjectArray().import(o, 'dat.path');

    i.data.should.eql({dat: {path: {
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    }}});
  });

  it('should use pull as an alias to dataset', function () {
    let o = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    o.pull().should.eql({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    o.pull('test2.test22').should.equal('fixture22');
  });

  it('should use pull as an alias to dataset with parent key', function () {
    let o = new ObjectArray({
      test: 'fixture',
      test2: {
        test21: 'fixture21',
        test22: 'fixture22'
      }
    });

    o.pull('test21', 'test2').should.equal('fixture21');
  });

  it('should create all needed keys', function () {
    let i = new ObjectArray();

    i.import({
      'dat.really.long.path': 'fixture1',
      'dat.really.long.dream': 'fixture2',
      'dat.shorter.path': 'fixture3'
    });
    i.data.should.eql({
      dat: {
        really: {
          long: {
            path: 'fixture1',
            dream: 'fixture2'
          }
        },
        shorter: {
          path: 'fixture3'
        }
      }
    });
  });
  it('should create all needed keys', function () {
    let i = new ObjectArray();

    i.push('dat.really.long.path', 'fixture1');
    i.push('dream', 'fixture2', 'dat.really.long');
    i.import({
      'shorter.path': 'fixture3'
    }, 'dat');
    i.data.should.eql({
      dat: {
        really: {
          long: {
            path: 'fixture1',
            dream: 'fixture2'
          }
        },
        shorter: {
          path: 'fixture3'
        }
      }
    });
  });
  it('should push simple data', function () {
    let i = new ObjectArray();

    i.push('test', 'fixture');
    i._data.should.eql({test: 'fixture'});
  });
  it('should remove simple data', function () {
    let i = new ObjectArray();

    i.push('test', 'fixture');
    i.remove('test');
    i._data.should.eql({});
  });

  it('should push dotted data', function () {
    let i = new ObjectArray();

    i.push('test.dot', 'fixture')
      .push('test.dot2', 'fixture2');
    i._data.should.eql({test: {dot: 'fixture', dot2: 'fixture2'}});
  });

  it('should remove dotted data', function () {
    let i = new ObjectArray();

    i.push('test.dot', 'fixture')
      .push('test.dot2', 'fixture2')
      .empty('test.dot2')
      ._data.should.eql({test: {dot: 'fixture'}});
  });

  it('should throw an exception if key not a string', function () {
    let i = new ObjectArray();

    expect(i.push.bind(i, new ObjectArray())).to.throw(TypeError);
  });

  it('should throw an exception if parent key is not a string', function () {
    let i = new ObjectArray();

    expect(i.push.bind(i, 'a', 0, new ObjectArray())).to.throw(TypeError);
  });
});

describe('Fetch and getset', function () {
  it('should getset data and throw an exception if inexistent key', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    // getters
    i.getset('test1')['get'].should.equal('fixture');
    i.getset('test2.testx.test2x')['get'].should.equal(0);
    i.getset('test2x', undefined, 'test2.testx')['get'].should.equal(0);
    i.getset(undefined, undefined, 'test2.testx')['get'].should.eql({test2x: 0});
    expect(i.getset.bind(i, 'test3')).to.throw(TypeError);
    expect(i.getset.bind(i, 'testx', undefined, 'test3')).to.throw(TypeError);

    // setters
    i.getset('test1', 'fixture2')['set'].should.be.true;
    i.pull('test1').should.equal('fixture2');
    i.getset('test2.testx', 'test1')['set'].should.be.true;
    i.pull('test2.testx').should.equal('test1');
    i.getset('testx', 'test2', 'test2')['set'].should.be.true;
    i.pull('testx', 'test2').should.equal('test2');
    i.getset({test3: 'test3'})['set'].should.be.true;
    i.pull('test3').should.equal('test3');
  });

  it('should pull data and returns undefined if inexistent key', function () {
    let i = new ObjectArray({
      test1: 'fixture',
      test2: {
        testx: { test2x: 0 },
        testy: {
          test2y1: true,
          test2y2: 'fix'
        }
      }
    });

    expect(i.pull('test3', null, false)).to.be.undefined;
    expect(i.getset('test3', undefined, '', false)['get']).to.be.undefined;
  });
});

/**
*  @test {ObjectArray#forEach}
*  @test {ObjectArray#reduce}
*/
describe('ObjectArray iterations', function () {
  it('should iterate a callback with forEach', function () {
    let i = new ObjectArray();

    let ret = {};

    let indexes = [];

    i.import({
      test: 'fixture',
      test2: 'fixture2'
    });

    i.forEach(function (value, key, index) {
      ret[key] = value;
      indexes.push(index);
    });

    ret.should.eql({
      test: 'fixture',
      test2: 'fixture2'
    });

    indexes.should.eql([0, 1]);
  });

  it('should iterate a callback with forEach on a dotted key', function () {
    let i = new ObjectArray();

    let ret = {};

    let indexes = [];

    i.import({
      test: {
        test: 'fixture',
        test2: 'fixture2'
      }
    });

    i.forEach(function (value, key, index) {
      ret[key] = value;
      indexes.push(index);
    }, 'test');

    ret.should.eql({
      test: 'fixture',
      test2: 'fixture2'
    });

    indexes.should.eql([0, 1]);
  });

  it('should throw an exception with forEach', function () {
    var i = new ObjectArray({
      test: {
        test: 'fixture',
        test2: 'fixture2'
      }
    });

    expect(i.forEach.bind(i, (v, k) => { i.remove(k); }, 'test3')).to.throw(TypeError);
  });

  it('should do nothing with forEach and bad key', function () {
    var i = new ObjectArray({
      test: {
        test: 'fixture',
        test2: 'fixture2'
      }
    });

    i.forEach((v, k) => { i.remove(k); }, 'test3', undefined, false);
    i._data.should.eql({
      test: {
        test: 'fixture',
        test2: 'fixture2'
      }
    });
  });

  it('should reduce the data', function () {
    let i = new ObjectArray({
      position: 'absolute',
      display: 'flex'
    });

    let ret = i.reduce(function (str, value, key) {
      str += key + ':' + value + ';';
      return str;
    }, '');

    ret.should.equal('position:absolute;display:flex;');
  });

  it('should reduce the data of a subset', function () {
    let i = new ObjectArray({
      style: {
        position: 'absolute',
        display: 'flex'
      }
    });

    let ret = i.reduce(function (str, value, key) {
      str += key + ':' + value + ';';
      return str;
    }, '', 'style');

    ret.should.equal('position:absolute;display:flex;');
  });
});

describe('Serializers', function () {
  it('should return a style type string', function () {
    let i = new ObjectArray({
      position: 'absolute',
      display: 'flex',
      paddingLeft: '1em'
    });

    i.stylesToString().should.equal('position:absolute;display:flex;padding-left:1em');
  });

  it('should return a style type string from subset or undefined', function () {
    let i = new ObjectArray({
      css: {
        position: 'absolute',
        display: 'flex',
        paddingLeft: '1em'
      }
    });

    i.stylesToString('css').should.equal('position:absolute;display:flex;padding-left:1em');
    expect(i.stylesToString('wrongcss', 'dat', false)).to.be.undefined;
  });

  it('should import a style type string', function () {
    let i = new ObjectArray();

    i.stringToStyles(undefined).data.should.eql({});
    i.stringToStyles(null).data.should.eql({});

    i.stringToStyles('position:absolute;display:flex;padding-left:1em')
      .data.should.eql({
        position: 'absolute',
        display: 'flex',
        paddingLeft: '1em'
      });

    i.empty();

    i.stringToStyles('position:absolute;display:flex;padding-left:1em', 'dat.path.to.subkey')
      .dataset('dat.path.to.subkey').should.eql({
        position: 'absolute',
        display: 'flex',
        paddingLeft: '1em'
      });

    i.stringToStyles('position:absolute;display:flex;padding-left:1em;', 'dat.path.to.subkey')
      .dataset('dat.path.to.subkey').should.eql({
        position: 'absolute',
        display: 'flex',
        paddingLeft: '1em'
      });
  });

  it('should throw an exception if bad string provided', function () {
    let i = new ObjectArray();

    expect(i.stringToStyles.bind(i, 'databadword')).to.throw('Malformed string for stringToStyles');
    expect(i.stringToStyles.bind(i, ':databadword;peanuts')).to.throw('Malformed string for stringToStyles');
  });

  it('should return a url encoded string', function () {
    let i = new ObjectArray({
      input: 'test',
      glob: '**/*',
      alias: 'test fixture'
    });

    let ret = i.urlEncode();

    ret.should.equal('input=test&glob=**%2F*&alias=test%20fixture');
  });

  it('should return a form url encoded string', function () {
    let i = new ObjectArray({
      input: 'test',
      glob: '**/*',
      alias: 'test fixture'
    });

    let ret = i.formUrlEncode();

    ret.should.equal('input=test&glob=**%2F*&alias=test+fixture');
  });

  it('should return undefined as form url encoded string with unknown key', function () {
    let i = new ObjectArray({
      input: 'test',
      glob: '**/*',
      alias: 'test fixture'
    });

    let ret = i.formUrlEncode('dat.bad.key', undefined, false);

    expect(ret).to.be.undefined;
  });
});

describe('Import JSON and change keys', function () {
  it('should import JSON and change keys', function () {
    var jstring = '{"dat": {"long": {"path": "foo", "dream": "baz"}}}';
    var doa = new ObjectArray(JSON.parse(jstring));

    doa.push('short', doa.dataset('dat.long')).remove('dat');
    JSON.stringify(doa.data).should.equal('{"short":{"path":"foo","dream":"baz"}}');
  });
});

/**
* @test {ObjectArray#camelize}
* @test {ObjectArray#dashize}
*/
describe('Camel and dash', function () {
  it('should camelize space and dashed strings', function () {
    let e = new ObjectArray();

    e.camelize('a long string').should.equal('aLongString');
    e.camelize('a LonG string').should.equal('aLonGString');
    e.camelize('a-long-string').should.equal('aLongString');
    e.camelize('a long-string').should.equal('aLongString');
    e.camelize('background-color').should.equal('backgroundColor');
    e.camelize('padding-left').should.equal('paddingLeft');
  });

  it('should dashize space and uppercase letter', function () {
    let e = new ObjectArray();

    e.dashize('a long string').should.equal('a-long-string');
    e.dashize('aLongString').should.equal('a-long-string');
    e.dashize('a LongString').should.equal('a-long-string');
    e.dashize('a longString').should.equal('a-long-string');
    e.dashize('backgroundColor').should.equal('background-color');
    e.dashize('paddingLeft').should.equal('padding-left');
    e.dashize('PaddingLeft').should.equal('padding-left');
  });
});

/**
 * @test #{ObjectArray#has}
 * @test #{ObjectArray#_key}
 * @test #{ObjectArray#pull}
 * @see https://github.com/liqueurdetoile/DotObjectArray/issues/1
 */
describe('Check subkey existence evaluation on various data types', function () {
  it('should return undefined if key does not exist under an empty object', function () {
    let e = new ObjectArray({object: {foo: {}}});

    e.has('object.foo.bar').should.be.false;
    expect(e._key('object.foo.bar')).to.be.undefined;
    expect(e.pull('object.foo.bar')).to.be.undefined;
  });

  it('should return undefined if key does not exist under a boolean value', function () {
    let e = new ObjectArray({object: {foo: true}});

    e.has('object.foo.bar').should.be.false;
    expect(e._key('object.foo.bar')).to.be.undefined;
    expect(e.pull('object.foo.bar')).to.be.undefined;
  });

  it('should return undefined if key does not exist under a null value', function () {
    let e = new ObjectArray({object: {foo: null}});

    e.has('object.foo.bar').should.be.false;
    expect(e._key('object.foo.bar')).to.be.undefined;
    expect(e.pull('object.foo.bar')).to.be.undefined;
  });

  it('should return undefined if key does not exist under a string value', function () {
    let e = new ObjectArray({object: {foo: 'test'}});

    e.has('object.foo.bar').should.be.false;
    expect(e._key('object.foo.bar')).to.be.undefined;
    expect(e.pull('object.foo.bar')).to.be.undefined;
  });
});