Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 61KB

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