PageRenderTime 160ms CodeModel.GetById 20ms app.highlight 129ms RepoModel.GetById 1ms app.codeStats 1ms

/node_modules/mpath/test/index.js

https://bitbucket.org/coleman333/smartsite
JavaScript | 1831 lines | 1561 code | 252 blank | 18 comment | 22 complexity | 479d715117a038be8538334a15cbe494 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1
   2/**
   3 * Test dependencies.
   4 */
   5
   6var mpath = require('../')
   7var assert = require('assert')
   8
   9/**
  10 * logging helper
  11 */
  12
  13function log (o) {
  14  console.log();
  15  console.log(require('util').inspect(o, false, 1000));
  16}
  17
  18/**
  19 * special path for override tests
  20 */
  21
  22var special = '_doc';
  23
  24/**
  25 * Tests
  26 */
  27
  28describe('mpath', function(){
  29
  30  /**
  31   * test doc creator
  32   */
  33
  34  function doc () {
  35    var o = { first: { second: { third: [3,{ name: 'aaron' }, 9] }}};
  36    o.comments = [
  37        { name: 'one' }
  38      , { name: 'two', _doc: { name: '2' }}
  39      , { name: 'three'
  40          , comments: [{},{ comments: [{val: 'twoo'}]}]
  41          , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]  }}
  42    ];
  43    o.name = 'jiro';
  44    o.array = [
  45        { o: { array: [{x: {b: [4,6,8]}}, { y: 10} ] }}
  46      , { o: { array: [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}] }}
  47      , { o: { array: [{x: {b: null }}, { x: { b: [null, 1]}}] }}
  48      , { o: { array: [{x: null }] }}
  49      , { o: { array: [{y: 3 }] }}
  50      , { o: { array: [3, 0, null] }}
  51      , { o: { name: 'ha' }}
  52    ];
  53    o.arr = [
  54        { arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
  55      , { yep: true }
  56    ]
  57    return o;
  58  }
  59
  60  describe('get', function(){
  61    var o = doc();
  62
  63    it('`path` must be a string or array', function(done){
  64      assert.throws(function () {
  65        mpath.get({}, o);
  66      }, /Must be either string or array/);
  67      assert.throws(function () {
  68        mpath.get(4, o);
  69      }, /Must be either string or array/);
  70      assert.throws(function () {
  71        mpath.get(function(){}, o);
  72      }, /Must be either string or array/);
  73      assert.throws(function () {
  74        mpath.get(/asdf/, o);
  75      }, /Must be either string or array/);
  76      assert.throws(function () {
  77        mpath.get(Math, o);
  78      }, /Must be either string or array/);
  79      assert.throws(function () {
  80        mpath.get(Buffer, o);
  81      }, /Must be either string or array/);
  82      assert.doesNotThrow(function () {
  83        mpath.get('string', o);
  84      });
  85      assert.doesNotThrow(function () {
  86        mpath.get([], o);
  87      });
  88      done();
  89    })
  90
  91    describe('without `special`', function(){
  92      it('works', function(done){
  93        assert.equal('jiro', mpath.get('name', o));
  94
  95        assert.deepEqual(
  96          { second: { third: [3,{ name: 'aaron' }, 9] }}
  97          , mpath.get('first', o)
  98        );
  99
 100        assert.deepEqual(
 101          { third: [3,{ name: 'aaron' }, 9] }
 102          , mpath.get('first.second', o)
 103        );
 104
 105        assert.deepEqual(
 106          [3,{ name: 'aaron' }, 9]
 107          , mpath.get('first.second.third', o)
 108        );
 109
 110        assert.deepEqual(
 111          3
 112          , mpath.get('first.second.third.0', o)
 113        );
 114
 115        assert.deepEqual(
 116          9
 117          , mpath.get('first.second.third.2', o)
 118        );
 119
 120        assert.deepEqual(
 121          { name: 'aaron' }
 122          , mpath.get('first.second.third.1', o)
 123        );
 124
 125        assert.deepEqual(
 126          'aaron'
 127          , mpath.get('first.second.third.1.name', o)
 128        );
 129
 130        assert.deepEqual([
 131            { name: 'one' }
 132          , { name: 'two', _doc: { name: '2' }}
 133          , { name: 'three'
 134            , comments: [{},{ comments: [{val: 'twoo'}]}]
 135            , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]}}],
 136          mpath.get('comments', o));
 137
 138        assert.deepEqual({ name: 'one' }, mpath.get('comments.0', o));
 139        assert.deepEqual('one', mpath.get('comments.0.name', o));
 140        assert.deepEqual('two', mpath.get('comments.1.name', o));
 141        assert.deepEqual('three', mpath.get('comments.2.name', o));
 142
 143        assert.deepEqual([{},{ comments: [{val: 'twoo'}]}]
 144            , mpath.get('comments.2.comments', o));
 145
 146        assert.deepEqual({ comments: [{val: 'twoo'}]}
 147            , mpath.get('comments.2.comments.1', o));
 148
 149        assert.deepEqual('twoo', mpath.get('comments.2.comments.1.comments.0.val', o));
 150
 151        done();
 152      })
 153
 154      it('handles array.property dot-notation', function(done){
 155        assert.deepEqual(
 156            ['one', 'two', 'three']
 157          , mpath.get('comments.name', o)
 158        );
 159        done();
 160      })
 161
 162      it('handles array.array notation', function(done){
 163        assert.deepEqual(
 164            [undefined, undefined, [{}, {comments:[{val:'twoo'}]}]]
 165          , mpath.get('comments.comments', o)
 166        );
 167        done();
 168      })
 169
 170      it('handles prop.prop.prop.arrayProperty notation', function(done){
 171        assert.deepEqual(
 172          [undefined, 'aaron', undefined]
 173          , mpath.get('first.second.third.name', o)
 174        );
 175        assert.deepEqual(
 176          [1, 'aaron', 1]
 177          , mpath.get('first.second.third.name', o, function (v) {
 178            return undefined === v ? 1 : v;
 179          })
 180        );
 181        done();
 182      })
 183
 184      it('handles array.prop.array', function(done){
 185        assert.deepEqual(
 186            [ [{x: {b: [4,6,8]}}, { y: 10} ]
 187            , [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}]
 188            , [{x: {b: null }}, { x: { b: [null, 1]}}]
 189            , [{x: null }]
 190            , [{y: 3 }]
 191            , [3, 0, null]
 192            , undefined
 193            ]
 194          , mpath.get('array.o.array', o)
 195        );
 196        done();
 197      })
 198
 199      it('handles array.prop.array.index', function(done){
 200        assert.deepEqual(
 201            [ {x: {b: [4,6,8]}}
 202            , {x: {b: [1,2,3]}}
 203            , {x: {b: null }}
 204            , {x: null }
 205            , {y: 3 }
 206            , 3
 207            , undefined
 208            ]
 209          , mpath.get('array.o.array.0', o)
 210        );
 211        done();
 212      })
 213
 214      it('handles array.prop.array.index.prop', function(done){
 215        assert.deepEqual(
 216            [ {b: [4,6,8]}
 217            , {b: [1,2,3]}
 218            , {b: null }
 219            , null
 220            , undefined
 221            , undefined
 222            , undefined
 223            ]
 224          , mpath.get('array.o.array.0.x', o)
 225        );
 226        done();
 227      })
 228
 229      it('handles array.prop.array.prop', function(done){
 230        assert.deepEqual(
 231            [ [undefined, 10 ]
 232            , [undefined, undefined, undefined]
 233            , [undefined, undefined]
 234            , [undefined]
 235            , [3]
 236            , [undefined, undefined, undefined]
 237            , undefined
 238            ]
 239          , mpath.get('array.o.array.y', o)
 240        );
 241        assert.deepEqual(
 242            [ [{b: [4,6,8]}, undefined]
 243            , [{b: [1,2,3]},  {z: 10 }, {b: 'hi'}]
 244            , [{b: null }, { b: [null, 1]}]
 245            , [null]
 246            , [undefined]
 247            , [undefined, undefined, undefined]
 248            , undefined
 249            ]
 250          , mpath.get('array.o.array.x', o)
 251        );
 252        done();
 253      })
 254
 255      it('handles array.prop.array.prop.prop', function(done){
 256        assert.deepEqual(
 257            [ [[4,6,8], undefined]
 258            , [[1,2,3], undefined, 'hi']
 259            , [null, [null, 1]]
 260            , [null]
 261            , [undefined]
 262            , [undefined, undefined, undefined]
 263            , undefined
 264            ]
 265          , mpath.get('array.o.array.x.b', o)
 266        );
 267        done();
 268      })
 269
 270      it('handles array.prop.array.prop.prop.index', function(done){
 271        assert.deepEqual(
 272            [ [6, undefined]
 273            , [2, undefined, 'i'] // undocumented feature (string indexing)
 274            , [null, 1]
 275            , [null]
 276            , [undefined]
 277            , [undefined, undefined, undefined]
 278            , undefined
 279            ]
 280          , mpath.get('array.o.array.x.b.1', o)
 281        );
 282        assert.deepEqual(
 283            [ [6, 0]
 284            , [2, 0, 'i'] // undocumented feature (string indexing)
 285            , [null, 1]
 286            , [null]
 287            , [0]
 288            , [0, 0, 0]
 289            , 0
 290            ]
 291          , mpath.get('array.o.array.x.b.1', o, function (v) {
 292            return undefined === v ? 0 : v;
 293          })
 294        );
 295        done();
 296      })
 297
 298      it('handles array.index.prop.prop', function(done){
 299        assert.deepEqual(
 300            [{x: {b: [1,2,3]}}, { x: {z: 10 }}, { x: {b: 'hi'}}]
 301          , mpath.get('array.1.o.array', o)
 302        );
 303        assert.deepEqual(
 304            ['hi','hi','hi']
 305          , mpath.get('array.1.o.array', o, function (v) {
 306            if (Array.isArray(v)) {
 307              return v.map(function (val) {
 308                return 'hi';
 309              })
 310            }
 311            return v;
 312          })
 313        );
 314        done();
 315      })
 316
 317      it('handles array.array.index', function(done){
 318        assert.deepEqual(
 319            [{ a: { c: 48 }}, undefined]
 320          , mpath.get('arr.arr.1', o)
 321        );
 322        assert.deepEqual(
 323            ['woot', undefined]
 324          , mpath.get('arr.arr.1', o, function (v) {
 325            if (v && v.a && v.a.c) return 'woot';
 326            return v;
 327          })
 328        );
 329        done();
 330      })
 331
 332      it('handles array.array.index.prop', function(done){
 333        assert.deepEqual(
 334            [{ c: 48 }, 'woot']
 335          , mpath.get('arr.arr.1.a', o, function (v) {
 336            if (undefined === v) return 'woot';
 337            return v;
 338          })
 339        );
 340        assert.deepEqual(
 341            [{ c: 48 }, undefined]
 342          , mpath.get('arr.arr.1.a', o)
 343        );
 344        mpath.set('arr.arr.1.a', [{c:49},undefined], o)
 345        assert.deepEqual(
 346            [{ c: 49 }, undefined]
 347          , mpath.get('arr.arr.1.a', o)
 348        );
 349        mpath.set('arr.arr.1.a', [{c:48},undefined], o)
 350        done();
 351      })
 352
 353      it('handles array.array.index.prop.prop', function(done){
 354        assert.deepEqual(
 355            [48, undefined]
 356          , mpath.get('arr.arr.1.a.c', o)
 357        );
 358        assert.deepEqual(
 359            [48, 'woot']
 360          , mpath.get('arr.arr.1.a.c', o, function (v) {
 361            if (undefined === v) return 'woot';
 362            return v;
 363          })
 364        );
 365        done();
 366      })
 367
 368    })
 369
 370    describe('with `special`', function(){
 371      describe('that is a string', function(){
 372        it('works', function(done){
 373          assert.equal('jiro', mpath.get('name', o, special));
 374
 375          assert.deepEqual(
 376            { second: { third: [3,{ name: 'aaron' }, 9] }}
 377            , mpath.get('first', o, special)
 378          );
 379
 380          assert.deepEqual(
 381            { third: [3,{ name: 'aaron' }, 9] }
 382            , mpath.get('first.second', o, special)
 383          );
 384
 385          assert.deepEqual(
 386            [3,{ name: 'aaron' }, 9]
 387            , mpath.get('first.second.third', o, special)
 388          );
 389
 390          assert.deepEqual(
 391            3
 392            , mpath.get('first.second.third.0', o, special)
 393          );
 394
 395          assert.deepEqual(
 396            4
 397            , mpath.get('first.second.third.0', o, special, function (v) {
 398              return 3 === v ? 4 : v;
 399            })
 400          );
 401
 402          assert.deepEqual(
 403            9
 404            , mpath.get('first.second.third.2', o, special)
 405          );
 406
 407          assert.deepEqual(
 408            { name: 'aaron' }
 409            , mpath.get('first.second.third.1', o, special)
 410          );
 411
 412          assert.deepEqual(
 413            'aaron'
 414            , mpath.get('first.second.third.1.name', o, special)
 415          );
 416
 417          assert.deepEqual([
 418              { name: 'one' }
 419            , { name: 'two', _doc: { name: '2' }}
 420            , { name: 'three'
 421              , comments: [{},{ comments: [{val: 'twoo'}]}]
 422              , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]}}],
 423            mpath.get('comments', o, special));
 424
 425          assert.deepEqual({ name: 'one' }, mpath.get('comments.0', o, special));
 426          assert.deepEqual('one', mpath.get('comments.0.name', o, special));
 427          assert.deepEqual('2', mpath.get('comments.1.name', o, special));
 428          assert.deepEqual('3', mpath.get('comments.2.name', o, special));
 429          assert.deepEqual('nice', mpath.get('comments.2.name', o, special, function (v) {
 430            return '3' === v ? 'nice' : v;
 431          }));
 432
 433          assert.deepEqual([{},{ _doc: { comments: [{ val: 2 }] }}]
 434              , mpath.get('comments.2.comments', o, special));
 435
 436          assert.deepEqual({ _doc: { comments: [{val: 2}]}}
 437              , mpath.get('comments.2.comments.1', o, special));
 438
 439          assert.deepEqual(2, mpath.get('comments.2.comments.1.comments.0.val', o, special));
 440          done();
 441        })
 442
 443        it('handles array.property dot-notation', function(done){
 444          assert.deepEqual(
 445            ['one', '2', '3']
 446            , mpath.get('comments.name', o, special)
 447          );
 448          assert.deepEqual(
 449            ['one', 2, '3']
 450            , mpath.get('comments.name', o, special, function (v) {
 451              return '2' === v ? 2 : v
 452            })
 453          );
 454          done();
 455        })
 456
 457        it('handles array.array notation', function(done){
 458          assert.deepEqual(
 459              [undefined, undefined, [{}, {_doc: { comments:[{val:2}]}}]]
 460            , mpath.get('comments.comments', o, special)
 461          );
 462          done();
 463        })
 464
 465        it('handles array.array.index.array', function(done){
 466          assert.deepEqual(
 467              [undefined, undefined, [{val:2}]]
 468            , mpath.get('comments.comments.1.comments', o, special)
 469          );
 470          done();
 471        })
 472
 473        it('handles array.array.index.array.prop', function(done){
 474          assert.deepEqual(
 475              [undefined, undefined, [2]]
 476            , mpath.get('comments.comments.1.comments.val', o, special)
 477          );
 478          assert.deepEqual(
 479              ['nil', 'nil', [2]]
 480            , mpath.get('comments.comments.1.comments.val', o, special, function (v) {
 481              return undefined === v ? 'nil' : v;
 482            })
 483          );
 484          done();
 485        })
 486      })
 487
 488      describe('that is a function', function(){
 489        var special = function (obj, key) {
 490          return obj[key]
 491        }
 492
 493        it('works', function(done){
 494          assert.equal('jiro', mpath.get('name', o, special));
 495
 496          assert.deepEqual(
 497            { second: { third: [3,{ name: 'aaron' }, 9] }}
 498            , mpath.get('first', o, special)
 499          );
 500
 501          assert.deepEqual(
 502            { third: [3,{ name: 'aaron' }, 9] }
 503            , mpath.get('first.second', o, special)
 504          );
 505
 506          assert.deepEqual(
 507            [3,{ name: 'aaron' }, 9]
 508            , mpath.get('first.second.third', o, special)
 509          );
 510
 511          assert.deepEqual(
 512            3
 513            , mpath.get('first.second.third.0', o, special)
 514          );
 515
 516          assert.deepEqual(
 517            4
 518            , mpath.get('first.second.third.0', o, special, function (v) {
 519              return 3 === v ? 4 : v;
 520            })
 521          );
 522
 523          assert.deepEqual(
 524            9
 525            , mpath.get('first.second.third.2', o, special)
 526          );
 527
 528          assert.deepEqual(
 529            { name: 'aaron' }
 530            , mpath.get('first.second.third.1', o, special)
 531          );
 532
 533          assert.deepEqual(
 534            'aaron'
 535            , mpath.get('first.second.third.1.name', o, special)
 536          );
 537
 538          assert.deepEqual([
 539              { name: 'one' }
 540            , { name: 'two', _doc: { name: '2' }}
 541            , { name: 'three'
 542              , comments: [{},{ comments: [{val: 'twoo'}]}]
 543              , _doc: { name: '3', comments: [{},{ _doc: { comments: [{ val: 2 }] }}]}}],
 544            mpath.get('comments', o, special));
 545
 546          assert.deepEqual({ name: 'one' }, mpath.get('comments.0', o, special));
 547          assert.deepEqual('one', mpath.get('comments.0.name', o, special));
 548          assert.deepEqual('two', mpath.get('comments.1.name', o, special));
 549          assert.deepEqual('three', mpath.get('comments.2.name', o, special));
 550          assert.deepEqual('nice', mpath.get('comments.2.name', o, special, function (v) {
 551            return 'three' === v ? 'nice' : v;
 552          }));
 553
 554          assert.deepEqual([{},{ comments: [{ val: 'twoo' }] }]
 555              , mpath.get('comments.2.comments', o, special));
 556
 557          assert.deepEqual({ comments: [{val: 'twoo'}]}
 558              , mpath.get('comments.2.comments.1', o, special));
 559
 560          assert.deepEqual('twoo', mpath.get('comments.2.comments.1.comments.0.val', o, special));
 561
 562          var overide = false;
 563          assert.deepEqual('twoo', mpath.get('comments.8.comments.1.comments.0.val', o, function (obj, path) {
 564            if (Array.isArray(obj) && 8 == path) {
 565              overide = true;
 566              return obj[2];
 567            }
 568            return obj[path];
 569          }));
 570          assert.ok(overide);
 571
 572          done();
 573        })
 574
 575        it('in combination with map', function(done){
 576          var special = function (obj, key) {
 577            if (Array.isArray(obj)) return obj[key];
 578            return obj.mpath;
 579          }
 580          var map = function (val) {
 581            return 'convert' == val
 582              ? 'mpath'
 583              : val;
 584          }
 585          var o = { mpath: [{ mpath: 'converse' }, { mpath: 'convert' }] }
 586
 587          assert.equal('mpath', mpath.get('something.1.kewl', o, special, map));
 588          done();
 589        })
 590      })
 591    })
 592  })
 593
 594  describe('set', function(){
 595    describe('without `special`', function(){
 596      var o = doc();
 597
 598      it('works', function(done){
 599        mpath.set('name', 'a new val', o, function (v) {
 600          return 'a new val' === v ? 'changed' : v;
 601        });
 602        assert.deepEqual('changed', o.name);
 603
 604        mpath.set('name', 'changed', o);
 605        assert.deepEqual('changed', o.name);
 606
 607        mpath.set('first.second.third', [1,{name:'x'},9], o);
 608        assert.deepEqual([1,{name:'x'},9], o.first.second.third);
 609
 610        mpath.set('first.second.third.1.name', 'y', o)
 611        assert.deepEqual([1,{name:'y'},9], o.first.second.third);
 612
 613        mpath.set('comments.1.name', 'ttwwoo', o);
 614        assert.deepEqual({ name: 'ttwwoo', _doc: { name: '2' }}, o.comments[1]);
 615
 616        mpath.set('comments.2.comments.1.comments.0.expand', 'added', o);
 617        assert.deepEqual(
 618            { val: 'twoo', expand: 'added'}
 619          , o.comments[2].comments[1].comments[0]);
 620
 621        mpath.set('comments.2.comments.1.comments.2', 'added', o);
 622        assert.equal(3, o.comments[2].comments[1].comments.length);
 623        assert.deepEqual(
 624            { val: 'twoo', expand: 'added'}
 625          , o.comments[2].comments[1].comments[0]);
 626        assert.deepEqual(
 627            undefined
 628          , o.comments[2].comments[1].comments[1]);
 629        assert.deepEqual(
 630            'added'
 631          , o.comments[2].comments[1].comments[2]);
 632
 633        done();
 634      })
 635
 636      describe('array.path', function(){
 637        describe('with single non-array value', function(){
 638          it('works', function(done){
 639            mpath.set('arr.yep', false, o, function (v) {
 640              return false === v ? true: v;
 641            });
 642            assert.deepEqual([
 643              { yep: true, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 644            , { yep: true }
 645            ], o.arr);
 646
 647            mpath.set('arr.yep', false, o);
 648
 649            assert.deepEqual([
 650              { yep: false, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 651            , { yep: false }
 652            ], o.arr);
 653
 654            done();
 655          })
 656        })
 657        describe('with array of values', function(){
 658          it('that are equal in length', function(done){
 659            mpath.set('arr.yep', ['one',2], o, function (v) {
 660              return 'one' === v ? 1 : v;
 661            });
 662            assert.deepEqual([
 663              { yep: 1, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 664            , { yep: 2 }
 665            ], o.arr);
 666            mpath.set('arr.yep', ['one',2], o);
 667
 668            assert.deepEqual([
 669              { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 670            , { yep: 2 }
 671            ], o.arr);
 672
 673            done();
 674          })
 675
 676          it('that is less than length', function(done){
 677            mpath.set('arr.yep', [47], o, function (v) {
 678              return 47 === v ? 4 : v;
 679            });
 680            assert.deepEqual([
 681              { yep: 4, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 682            , { yep: 2 }
 683            ], o.arr);
 684
 685            mpath.set('arr.yep', [47], o);
 686            assert.deepEqual([
 687              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 688            , { yep: 2 }
 689            ], o.arr);
 690
 691            done();
 692          })
 693
 694          it('that is greater than length', function(done){
 695            mpath.set('arr.yep', [5,6,7], o, function (v) {
 696              return 5 === v ? 'five' : v;
 697            });
 698            assert.deepEqual([
 699              { yep: 'five', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 700            , { yep: 6 }
 701            ], o.arr);
 702
 703            mpath.set('arr.yep', [5,6,7], o);
 704            assert.deepEqual([
 705              { yep: 5, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 706            , { yep: 6 }
 707            ], o.arr);
 708
 709            done();
 710          })
 711        })
 712      })
 713
 714      describe('array.$.path', function(){
 715        describe('with single non-array value', function(){
 716          it('copies the value to each item in array', function(done){
 717            mpath.set('arr.$.yep', {xtra: 'double good'}, o, function (v) {
 718              return v && v.xtra ? 'hi' : v;
 719            });
 720            assert.deepEqual([
 721              { yep: 'hi', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 722            , { yep: 'hi'}
 723            ], o.arr);
 724
 725            mpath.set('arr.$.yep', {xtra: 'double good'}, o);
 726            assert.deepEqual([
 727              { yep: {xtra:'double good'}, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 728            , { yep: {xtra:'double good'}}
 729            ], o.arr);
 730
 731            done();
 732          })
 733        })
 734        describe('with array of values', function(){
 735          it('copies the value to each item in array', function(done){
 736            mpath.set('arr.$.yep', [15], o, function (v) {
 737              return v.length === 1 ? [] : v;
 738            });
 739            assert.deepEqual([
 740              { yep: [], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 741            , { yep: []}
 742            ], o.arr);
 743
 744            mpath.set('arr.$.yep', [15], o);
 745            assert.deepEqual([
 746              { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 747            , { yep: [15]}
 748            ], o.arr);
 749
 750            done();
 751          })
 752        })
 753      })
 754
 755      describe('array.index.path', function(){
 756        it('works', function(done){
 757          mpath.set('arr.1.yep', 0, o, function (v) {
 758            return 0 === v ? 'zero' : v;
 759          });
 760          assert.deepEqual([
 761            { yep: [15] , arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 762          , { yep: 'zero' }
 763          ], o.arr);
 764
 765          mpath.set('arr.1.yep', 0, o);
 766          assert.deepEqual([
 767            { yep: [15] , arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
 768          , { yep: 0 }
 769          ], o.arr);
 770
 771          done();
 772        })
 773      })
 774
 775      describe('array.index.array.path', function(){
 776        it('with single value', function(done){
 777          mpath.set('arr.0.arr.e', 35, o, function (v) {
 778            return 35 === v ? 3 : v;
 779          });
 780          assert.deepEqual([
 781            { yep: [15], arr: [{ a: { b: 47 }, e: 3}, { a: { c: 48 }, e: 3}, { d: 'yep', e: 3 }] }
 782          , { yep: 0 }
 783          ], o.arr);
 784
 785          mpath.set('arr.0.arr.e', 35, o);
 786          assert.deepEqual([
 787            { yep: [15], arr: [{ a: { b: 47 }, e: 35}, { a: { c: 48 }, e: 35}, { d: 'yep', e: 35 }] }
 788          , { yep: 0 }
 789          ], o.arr);
 790
 791          done();
 792        })
 793        it('with array', function(done){
 794          mpath.set('arr.0.arr.e', ['a','b'], o, function (v) {
 795            return 'a' === v ? 'x' : v;
 796          });
 797          assert.deepEqual([
 798            { yep: [15], arr: [{ a: { b: 47 }, e: 'x'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] }
 799          , { yep: 0 }
 800          ], o.arr);
 801
 802          mpath.set('arr.0.arr.e', ['a','b'], o);
 803          assert.deepEqual([
 804            { yep: [15], arr: [{ a: { b: 47 }, e: 'a'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] }
 805          , { yep: 0 }
 806          ], o.arr);
 807
 808          done();
 809        })
 810      })
 811
 812      describe('array.index.array.path.path', function(){
 813        it('with single value', function(done){
 814          mpath.set('arr.0.arr.a.b', 36, o, function (v) {
 815            return 36 === v ? 3 : v;
 816          });
 817          assert.deepEqual([
 818            { yep: [15], arr: [{ a: { b: 3 }, e: 'a'}, { a: { c: 48, b: 3 }, e: 'b'}, { d: 'yep', e: 35 }] }
 819          , { yep: 0 }
 820          ], o.arr);
 821
 822          mpath.set('arr.0.arr.a.b', 36, o);
 823          assert.deepEqual([
 824            { yep: [15], arr: [{ a: { b: 36 }, e: 'a'}, { a: { c: 48, b: 36 }, e: 'b'}, { d: 'yep', e: 35 }] }
 825          , { yep: 0 }
 826          ], o.arr);
 827
 828          done();
 829        })
 830        it('with array', function(done){
 831          mpath.set('arr.0.arr.a.b', [1,2,3,4], o, function (v) {
 832            return 2 === v ? 'two' : v;
 833          });
 834          assert.deepEqual([
 835            { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 'two' }, e: 'b'}, { d: 'yep', e: 35 }] }
 836          , { yep: 0 }
 837          ], o.arr);
 838
 839          mpath.set('arr.0.arr.a.b', [1,2,3,4], o);
 840          assert.deepEqual([
 841            { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 2 }, e: 'b'}, { d: 'yep', e: 35 }] }
 842          , { yep: 0 }
 843          ], o.arr);
 844
 845          done();
 846        })
 847      })
 848
 849      describe('array.index.array.$.path.path', function(){
 850        it('with single value', function(done){
 851          mpath.set('arr.0.arr.$.a.b', '$', o, function (v) {
 852            return '$' === v ? 'dolla billz' : v;
 853          });
 854          assert.deepEqual([
 855            { yep: [15], arr: [{ a: { b: 'dolla billz' }, e: 'a'}, { a: { c: 48, b: 'dolla billz' }, e: 'b'}, { d: 'yep', e: 35 }] }
 856          , { yep: 0 }
 857          ], o.arr);
 858
 859          mpath.set('arr.0.arr.$.a.b', '$', o);
 860          assert.deepEqual([
 861            { yep: [15], arr: [{ a: { b: '$' }, e: 'a'}, { a: { c: 48, b: '$' }, e: 'b'}, { d: 'yep', e: 35 }] }
 862          , { yep: 0 }
 863          ], o.arr);
 864
 865          done();
 866        })
 867        it('with array', function(done){
 868          mpath.set('arr.0.arr.$.a.b', [1], o, function (v) {
 869            return Array.isArray(v) ? {} : v;
 870          });
 871          assert.deepEqual([
 872            { yep: [15], arr: [{ a: { b: {} }, e: 'a'}, { a: { c: 48, b: {} }, e: 'b'}, { d: 'yep', e: 35 }] }
 873          , { yep: 0 }
 874          ], o.arr);
 875
 876          mpath.set('arr.0.arr.$.a.b', [1], o);
 877          assert.deepEqual([
 878            { yep: [15], arr: [{ a: { b: [1] }, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 879          , { yep: 0 }
 880          ], o.arr);
 881
 882          done();
 883        })
 884      })
 885
 886      describe('array.array.index.path', function(){
 887        it('with single value', function(done){
 888          mpath.set('arr.arr.0.a', 'single', o, function (v) {
 889            return 'single' === v ? 'double' : v;
 890          });
 891          assert.deepEqual([
 892            { yep: [15], arr: [{ a: 'double', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 893          , { yep: 0 }
 894          ], o.arr);
 895
 896          mpath.set('arr.arr.0.a', 'single', o);
 897          assert.deepEqual([
 898            { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 899          , { yep: 0 }
 900          ], o.arr);
 901
 902          done();
 903        })
 904        it('with array', function(done){
 905          mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, function (v) {
 906            return 4 === v ? 3 : v;
 907          });
 908          assert.deepEqual([
 909            { yep: [15], arr: [{ a: 3, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 910          , { yep: false }
 911          ], o.arr);
 912
 913          mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o);
 914          assert.deepEqual([
 915            { yep: [15], arr: [{ a: 4, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 916          , { yep: false }
 917          ], o.arr);
 918
 919          done();
 920        })
 921      })
 922
 923      describe('array.array.$.index.path', function(){
 924        it('with single value', function(done){
 925          mpath.set('arr.arr.$.0.a', 'singles', o, function (v) {
 926            return 0;
 927          });
 928          assert.deepEqual([
 929            { yep: [15], arr: [{ a: 0, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 930          , { yep: 0 }
 931          ], o.arr);
 932
 933          mpath.set('arr.arr.$.0.a', 'singles', o);
 934          assert.deepEqual([
 935            { yep: [15], arr: [{ a: 'singles', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 936          , { yep: 0 }
 937          ], o.arr);
 938
 939          mpath.set('$.arr.arr.0.a', 'single', o);
 940          assert.deepEqual([
 941            { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 942          , { yep: 0 }
 943          ], o.arr);
 944
 945          done();
 946        })
 947        it('with array', function(done){
 948          mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o, function (v) {
 949            return 'nope'
 950          });
 951          assert.deepEqual([
 952            { yep: [15], arr: [{ a: 'nope', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 953          , { yep: 0}
 954          ], o.arr);
 955
 956          mpath.set('arr.arr.$.0.a', [4,8,15,16,23,42], o);
 957          assert.deepEqual([
 958            { yep: [15], arr: [{ a: [4,8,15,16,23,42], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 959          , { yep: 0}
 960          ], o.arr);
 961
 962          mpath.set('arr.$.arr.0.a', [4,8,15,16,23,42,108], o);
 963          assert.deepEqual([
 964            { yep: [15], arr: [{ a: [4,8,15,16,23,42,108], e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] }
 965          , { yep: 0}
 966          ], o.arr);
 967
 968          done();
 969        })
 970      })
 971
 972      describe('array.array.path.index', function(){
 973        it('with single value', function(done){
 974          mpath.set('arr.arr.a.7', 47, o, function (v) {
 975            return 1
 976          });
 977          assert.deepEqual([
 978            { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,1], e: 'a'}, { a: { c: 48, b: [1], '7': 1 }, e: 'b'}, { d: 'yep', e: 35 }] }
 979          , { yep: 0}
 980          ], o.arr);
 981
 982          mpath.set('arr.arr.a.7', 47, o);
 983          assert.deepEqual([
 984            { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,47], e: 'a'}, { a: { c: 48, b: [1], '7': 47 }, e: 'b'}, { d: 'yep', e: 35 }] }
 985          , { yep: 0}
 986          ], o.arr);
 987
 988          done();
 989        })
 990        it('with array', function(done){
 991          o.arr[1].arr = [{ a: [] }, { a: [] }, { a: null }];
 992          mpath.set('arr.arr.a.7', [[null,46], [undefined, 'woot']], o);
 993
 994          var a1 = [];
 995          var a2 = [];
 996          a1[7] = undefined;
 997          a2[7] = 'woot';
 998
 999          assert.deepEqual([
1000            { yep: [15], arr: [{ a: [4,8,15,16,23,42,108,null], e: 'a'}, { a: { c: 48, b: [1], '7': 46 }, e: 'b'}, { d: 'yep', e: 35 }] }
1001          , { yep: 0, arr: [{a:a1},{a:a2},{a:null}] }
1002          ], o.arr);
1003
1004          done();
1005        })
1006      })
1007
1008      describe('handles array.array.path', function(){
1009        it('with single', function(done){
1010          o.arr[1].arr = [{},{}];
1011          assert.deepEqual([{},{}], o.arr[1].arr);
1012          o.arr.push({ arr: 'something else' });
1013          o.arr.push({ arr: ['something else'] });
1014          o.arr.push({ arr: [[]] });
1015          o.arr.push({ arr: [5] });
1016
1017          var weird = [];
1018          weird.e = 'xmas';
1019
1020          // test
1021          mpath.set('arr.arr.e', 47, o, function (v) {
1022            return 'xmas'
1023          });
1024          assert.deepEqual([
1025            { yep: [15], arr: [
1026                  { a: [4,8,15,16,23,42,108,null], e: 'xmas'}
1027                , { a: { c: 48, b: [1], '7': 46 }, e: 'xmas'}
1028                , { d: 'yep', e: 'xmas' }
1029              ]
1030            }
1031          , { yep: 0, arr: [{e: 'xmas'}, {e:'xmas'}] }
1032          , { arr: 'something else' }
1033          , { arr: ['something else'] }
1034          , { arr: [weird] }
1035          , { arr: [5] }
1036          ]
1037          , o.arr);
1038
1039          weird.e = 47;
1040
1041          mpath.set('arr.arr.e', 47, o);
1042          assert.deepEqual([
1043            { yep: [15], arr: [
1044                  { a: [4,8,15,16,23,42,108,null], e: 47}
1045                , { a: { c: 48, b: [1], '7': 46 }, e: 47}
1046                , { d: 'yep', e: 47 }
1047              ]
1048            }
1049          , { yep: 0, arr: [{e: 47}, {e:47}] }
1050          , { arr: 'something else' }
1051          , { arr: ['something else'] }
1052          , { arr: [weird] }
1053          , { arr: [5] }
1054          ]
1055          , o.arr);
1056
1057          done();
1058        })
1059        it('with arrays', function(done){
1060          mpath.set('arr.arr.e', [[1,2,3],[4,5],null,[],[6], [7,8,9]], o, function (v) {
1061            return 10;
1062          });
1063
1064          var weird = [];
1065          weird.e = 10;
1066
1067          assert.deepEqual([
1068            { yep: [15], arr: [
1069                  { a: [4,8,15,16,23,42,108,null], e: 10}
1070                , { a: { c: 48, b: [1], '7': 46 }, e: 10}
1071                , { d: 'yep', e: 10 }
1072              ]
1073            }
1074          , { yep: 0, arr: [{e: 10}, {e:10}] }
1075          , { arr: 'something else' }
1076          , { arr: ['something else'] }
1077          , { arr: [weird] }
1078          , { arr: [5] }
1079          ]
1080          , o.arr);
1081
1082          mpath.set('arr.arr.e', [[1,2,3],[4,5],null,[],[6], [7,8,9]], o);
1083
1084          weird.e = 6;
1085
1086          assert.deepEqual([
1087            { yep: [15], arr: [
1088                  { a: [4,8,15,16,23,42,108,null], e: 1}
1089                , { a: { c: 48, b: [1], '7': 46 }, e: 2}
1090                , { d: 'yep', e: 3 }
1091              ]
1092            }
1093          , { yep: 0, arr: [{e: 4}, {e:5}] }
1094          , { arr: 'something else' }
1095          , { arr: ['something else'] }
1096          , { arr: [weird] }
1097          , { arr: [5] }
1098          ]
1099          , o.arr);
1100
1101          done();
1102        })
1103      })
1104    })
1105
1106    describe('with `special`', function(){
1107      var o = doc();
1108
1109      it('works', function(done){
1110        mpath.set('name', 'chan', o, special, function (v) {
1111          return 'hi';
1112        });
1113        assert.deepEqual('hi', o.name);
1114
1115        mpath.set('name', 'changer', o, special);
1116        assert.deepEqual('changer', o.name);
1117
1118        mpath.set('first.second.third', [1,{name:'y'},9], o, special);
1119        assert.deepEqual([1,{name:'y'},9], o.first.second.third);
1120
1121        mpath.set('first.second.third.1.name', 'z', o, special)
1122        assert.deepEqual([1,{name:'z'},9], o.first.second.third);
1123
1124        mpath.set('comments.1.name', 'ttwwoo', o, special);
1125        assert.deepEqual({ name: 'two', _doc: { name: 'ttwwoo' }}, o.comments[1]);
1126
1127        mpath.set('comments.2.comments.1.comments.0.expander', 'adder', o, special, function (v) {
1128          return 'super'
1129        });
1130        assert.deepEqual(
1131            { val: 2, expander: 'super'}
1132          , o.comments[2]._doc.comments[1]._doc.comments[0]);
1133
1134        mpath.set('comments.2.comments.1.comments.0.expander', 'adder', o, special);
1135        assert.deepEqual(
1136            { val: 2, expander: 'adder'}
1137          , o.comments[2]._doc.comments[1]._doc.comments[0]);
1138
1139        mpath.set('comments.2.comments.1.comments.2', 'set', o, special);
1140        assert.equal(3, o.comments[2]._doc.comments[1]._doc.comments.length);
1141        assert.deepEqual(
1142            { val: 2, expander: 'adder'}
1143          , o.comments[2]._doc.comments[1]._doc.comments[0]);
1144        assert.deepEqual(
1145            undefined
1146          , o.comments[2]._doc.comments[1]._doc.comments[1]);
1147        assert.deepEqual(
1148            'set'
1149          , o.comments[2]._doc.comments[1]._doc.comments[2]);
1150        done();
1151      })
1152
1153      describe('array.path', function(){
1154        describe('with single non-array value', function(){
1155          it('works', function(done){
1156            o.arr[1]._doc = { special: true }
1157
1158            mpath.set('arr.yep', false, o, special, function (v) {
1159              return 'yes';
1160            });
1161            assert.deepEqual([
1162              { yep: 'yes', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1163            , { yep: true, _doc: { special: true, yep: 'yes'}}
1164            ], o.arr);
1165
1166            mpath.set('arr.yep', false, o, special);
1167            assert.deepEqual([
1168              { yep: false, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1169            , { yep: true, _doc: { special: true, yep: false }}
1170            ], o.arr);
1171
1172            done();
1173          })
1174        })
1175        describe('with array of values', function(){
1176          it('that are equal in length', function(done){
1177            mpath.set('arr.yep', ['one',2], o, special, function (v) {
1178              return 2 === v ? 20 : v;
1179            });
1180            assert.deepEqual([
1181              { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1182            , { yep: true, _doc: { special: true, yep: 20}}
1183            ], o.arr);
1184
1185            mpath.set('arr.yep', ['one',2], o, special);
1186            assert.deepEqual([
1187              { yep: 'one', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1188            , { yep: true, _doc: { special: true, yep: 2}}
1189            ], o.arr);
1190
1191            done();
1192          })
1193
1194          it('that is less than length', function(done){
1195            mpath.set('arr.yep', [47], o, special, function (v) {
1196              return 80;
1197            });
1198            assert.deepEqual([
1199              { yep: 80, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1200            , { yep: true, _doc: { special: true, yep: 2}}
1201            ], o.arr);
1202
1203            mpath.set('arr.yep', [47], o, special);
1204            assert.deepEqual([
1205              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1206            , { yep: true, _doc: { special: true, yep: 2}}
1207            ], o.arr);
1208
1209            // add _doc to first element
1210            o.arr[0]._doc = { yep: 46, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] }
1211
1212            mpath.set('arr.yep', [20], o, special);
1213            assert.deepEqual([
1214              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 20, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1215            , { yep: true, _doc: { special: true, yep: 2}}
1216            ], o.arr);
1217
1218            done();
1219          })
1220
1221          it('that is greater than length', function(done){
1222            mpath.set('arr.yep', [5,6,7], o, special, function () {
1223              return 'x';
1224            });
1225            assert.deepEqual([
1226              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 'x', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1227            , { yep: true, _doc: { special: true, yep: 'x'}}
1228            ], o.arr);
1229
1230            mpath.set('arr.yep', [5,6,7], o, special);
1231            assert.deepEqual([
1232              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }], _doc: { yep: 5, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1233            , { yep: true, _doc: { special: true, yep: 6}}
1234            ], o.arr);
1235
1236            done();
1237          })
1238        })
1239      })
1240
1241      describe('array.$.path', function(){
1242        describe('with single non-array value', function(){
1243          it('copies the value to each item in array', function(done){
1244            mpath.set('arr.$.yep', {xtra: 'double good'}, o, special, function (v) {
1245              return 9;
1246            });
1247            assert.deepEqual([
1248              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1249                , _doc: { yep: 9, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1250            , { yep: true, _doc: { special: true, yep: 9}}
1251            ], o.arr);
1252
1253            mpath.set('arr.$.yep', {xtra: 'double good'}, o, special);
1254            assert.deepEqual([
1255              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1256                , _doc: { yep: {xtra:'double good'}, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1257            , { yep: true, _doc: { special: true, yep: {xtra:'double good'}}}
1258            ], o.arr);
1259
1260            done();
1261          })
1262        })
1263        describe('with array of values', function(){
1264          it('copies the value to each item in array', function(done){
1265            mpath.set('arr.$.yep', [15], o, special, function (v) {
1266              return 'array'
1267            });
1268            assert.deepEqual([
1269              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1270                , _doc: { yep: 'array', arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1271            , { yep: true, _doc: { special: true, yep: 'array'}}
1272            ], o.arr);
1273
1274            mpath.set('arr.$.yep', [15], o, special);
1275            assert.deepEqual([
1276              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1277                , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1278            , { yep: true, _doc: { special: true, yep: [15]}}
1279            ], o.arr);
1280
1281            done();
1282          })
1283        })
1284      })
1285
1286      describe('array.index.path', function(){
1287        it('works', function(done){
1288          mpath.set('arr.1.yep', 0, o, special, function (v) {
1289            return 1;
1290          });
1291          assert.deepEqual([
1292              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1293                , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1294            , { yep: true, _doc: { special: true, yep: 1}}
1295          ], o.arr);
1296
1297          mpath.set('arr.1.yep', 0, o, special);
1298          assert.deepEqual([
1299              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1300                , _doc: { yep: [15], arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }] } }
1301            , { yep: true, _doc: { special: true, yep: 0}}
1302          ], o.arr);
1303
1304          done();
1305        })
1306      })
1307
1308      describe('array.index.array.path', function(){
1309        it('with single value', function(done){
1310          mpath.set('arr.0.arr.e', 35, o, special, function (v) {
1311            return 30
1312          });
1313          assert.deepEqual([
1314              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1315                , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 30}, { a: { c: 48 }, e: 30}, { d: 'yep', e: 30 }] } }
1316            , { yep: true, _doc: { special: true, yep: 0}}
1317          ], o.arr);
1318
1319          mpath.set('arr.0.arr.e', 35, o, special);
1320          assert.deepEqual([
1321              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1322                , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 35}, { a: { c: 48 }, e: 35}, { d: 'yep', e: 35 }] } }
1323            , { yep: true, _doc: { special: true, yep: 0}}
1324          ], o.arr);
1325
1326          done();
1327        })
1328        it('with array', function(done){
1329          mpath.set('arr.0.arr.e', ['a','b'], o, special, function (v) {
1330            return 'a' === v ? 'A' : v;
1331          });
1332          assert.deepEqual([
1333              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1334                , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 'A'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1335            , { yep: true, _doc: { special: true, yep: 0}}
1336          ], o.arr);
1337
1338          mpath.set('arr.0.arr.e', ['a','b'], o, special);
1339          assert.deepEqual([
1340              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1341                , _doc: { yep: [15], arr: [{ a: { b: 47 }, e: 'a'}, { a: { c: 48 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1342            , { yep: true, _doc: { special: true, yep: 0}}
1343          ], o.arr);
1344
1345          done();
1346        })
1347      })
1348
1349      describe('array.index.array.path.path', function(){
1350        it('with single value', function(done){
1351          mpath.set('arr.0.arr.a.b', 36, o, special, function (v) {
1352            return 20
1353          });
1354          assert.deepEqual([
1355              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1356                , _doc: { yep: [15], arr: [{ a: { b: 20 }, e: 'a'}, { a: { c: 48, b: 20 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1357            , { yep: true, _doc: { special: true, yep: 0}}
1358          ], o.arr);
1359
1360          mpath.set('arr.0.arr.a.b', 36, o, special);
1361          assert.deepEqual([
1362              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1363                , _doc: { yep: [15], arr: [{ a: { b: 36 }, e: 'a'}, { a: { c: 48, b: 36 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1364            , { yep: true, _doc: { special: true, yep: 0}}
1365          ], o.arr);
1366
1367          done();
1368        })
1369        it('with array', function(done){
1370          mpath.set('arr.0.arr.a.b', [1,2,3,4], o, special, function (v) {
1371            return v*2;
1372          });
1373          assert.deepEqual([
1374              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1375                , _doc: { yep: [15], arr: [{ a: { b: 2 }, e: 'a'}, { a: { c: 48, b: 4 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1376            , { yep: true, _doc: { special: true, yep: 0}}
1377          ], o.arr);
1378
1379          mpath.set('arr.0.arr.a.b', [1,2,3,4], o, special);
1380          assert.deepEqual([
1381              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1382                , _doc: { yep: [15], arr: [{ a: { b: 1 }, e: 'a'}, { a: { c: 48, b: 2 }, e: 'b'}, { d: 'yep', e: 35 }] } }
1383            , { yep: true, _doc: { special: true, yep: 0}}
1384          ], o.arr);
1385
1386          done();
1387        })
1388      })
1389
1390      describe('array.index.array.$.path.path', function(){
1391        it('with single value', function(done){
1392          mpath.set('arr.0.arr.$.a.b', '$', o, special, function (v) {
1393            return 'dollaz'
1394          });
1395          assert.deepEqual([
1396              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1397                , _doc: { yep: [15], arr: [{ a: { b: 'dollaz' }, e: 'a'}, { a: { c: 48, b: 'dollaz' }, e: 'b'}, { d: 'yep', e: 35 }] } }
1398            , { yep: true, _doc: { special: true, yep: 0}}
1399          ], o.arr);
1400
1401          mpath.set('arr.0.arr.$.a.b', '$', o, special);
1402          assert.deepEqual([
1403              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1404                , _doc: { yep: [15], arr: [{ a: { b: '$' }, e: 'a'}, { a: { c: 48, b: '$' }, e: 'b'}, { d: 'yep', e: 35 }] } }
1405            , { yep: true, _doc: { special: true, yep: 0}}
1406          ], o.arr);
1407
1408          done();
1409        })
1410        it('with array', function(done){
1411          mpath.set('arr.0.arr.$.a.b', [1], o, special, function (v) {
1412            return {};
1413          });
1414          assert.deepEqual([
1415              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1416                , _doc: { yep: [15], arr: [{ a: { b: {} }, e: 'a'}, { a: { c: 48, b: {} }, e: 'b'}, { d: 'yep', e: 35 }] } }
1417            , { yep: true, _doc: { special: true, yep: 0}}
1418          ], o.arr);
1419
1420          mpath.set('arr.0.arr.$.a.b', [1], o, special);
1421          assert.deepEqual([
1422              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1423                , _doc: { yep: [15], arr: [{ a: { b: [1] }, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1424            , { yep: true, _doc: { special: true, yep: 0}}
1425          ], o.arr);
1426
1427          done();
1428        })
1429      })
1430
1431      describe('array.array.index.path', function(){
1432        it('with single value', function(done){
1433          mpath.set('arr.arr.0.a', 'single', o, special, function (v) {
1434            return 88;
1435          });
1436          assert.deepEqual([
1437              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1438                , _doc: { yep: [15], arr: [{ a: 88, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1439            , { yep: true, _doc: { special: true, yep: 0}}
1440          ], o.arr);
1441
1442          mpath.set('arr.arr.0.a', 'single', o, special);
1443          assert.deepEqual([
1444              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1445                , _doc: { yep: [15], arr: [{ a: 'single', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1446            , { yep: true, _doc: { special: true, yep: 0}}
1447          ], o.arr);
1448
1449          done();
1450        })
1451        it('with array', function(done){
1452          mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, special, function (v) {
1453            return v*2;
1454          });
1455          assert.deepEqual([
1456              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1457                , _doc: { yep: [15], arr: [{ a: 8, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1458            , { yep: true, _doc: { special: true, yep: 0}}
1459          ], o.arr);
1460
1461          mpath.set('arr.arr.0.a', [4,8,15,16,23,42], o, special);
1462          assert.deepEqual([
1463              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1464                , _doc: { yep: [15], arr: [{ a: 4, e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1465            , { yep: true, _doc: { special: true, yep: 0}}
1466          ], o.arr);
1467
1468          done();
1469        })
1470      })
1471
1472      describe('array.array.$.index.path', function(){
1473        it('with single value', function(done){
1474          mpath.set('arr.arr.$.0.a', 'singles', o, special, function (v) {
1475            return v.toUpperCase();
1476          });
1477          assert.deepEqual([
1478              { yep: 47, arr: [{ a: { b: 47 }}, { a: { c: 48 }}, { d: 'yep' }]
1479                , _doc: { yep: [15], arr: [{ a: 'SINGLES', e: 'a'}, { a: { c: 48, b: [1] }, e: 'b'}, { d: 'yep', e: 35 }] } }
1480            , { yep: true, _doc: { special: true, yep: 0}}
1481          ], o.arr);
1482
1483          mpath.set('arr.arr.$.0.a', 'singles', o, special);
1484          assert

Large files files are truncated, but you can click here to view the full file