UNPKG

update-immutable

Version:

React-compatible data-structure update utility

487 lines (395 loc) 9.48 kB
"use strict"; var update = require("../dist/update").default; var clone = require('clone'); function apply_update(test, desc, input, update_v, expected) { var orig = clone(input); var output; try { output = update(input, update_v); } catch (err) { console.error("Caught exception in apply_update:", err); throw(err); } test.deepEqual(output, expected, "update applied correctly: " + desc); test.ok(input != output, "new structure created: " + desc); test.deepEqual(input, orig, "original not modified: " + desc); } function apply_update_unchanged(test, desc, input, update_v) { var orig = clone(input); var output; try { output = update(input, update_v); } catch (err) { console.error("Caught exception in apply_update_unchanged:", err); throw(err); } test.deepEqual(output, orig, "update applied correctly (no change): " + desc); test.ok(input === output, "shallow equality retained: " + desc); } exports.testUpdate = function(test){ // set apply_update(test, "simple set", {}, { a: { $set: 1} }, { a: 1 } ); apply_update_unchanged(test, "no-op", { a: 1 }, {}, { a: 1 } ); apply_update(test, "nested set", { a: { b: 1 }, c: 2 }, { a: { b: { '$set': 5 } } }, { a: { b: 5 }, c: 2 } ); apply_update(test, "set, auto-vivify", { c: 2 }, { a: { b: { '$set': 5 } } }, { a: { b: 5 }, c: 2 } ); apply_update(test, "set array", { a: [ 0, ], }, { a: { 0: { '$set': 9 } } }, { a: [ 9 ] } ); apply_update(test, "set array, new index", { a: [ 0, ], }, { a: { 1: { '$set': 9 } } }, { a: [ 0, 9 ] } ); apply_update(test, "set array, new index leaving gap", { a: [ 0, ], }, { a: { 4: { '$set': 9 } } }, { a: [ 0,,,,9 ] } ); { let input = { items: [ "a", "b" ] }; input.items.top = 0; let output = { items: [ "a", "c" ] }; output.items.top = 0; apply_update(test, "set array, non-numeric keys are preserved", input, { items: { 1: { '$set': "c" } } }, output ); } apply_update(test, "set key to undefined", { a: { y: 1 } }, { a: { x: { '$set': undefined } } }, { a: { x: undefined, y: 1 } } ); apply_update(test, "set key to null", { a: { y: 1 } }, { a: { x: { '$set': null } } }, { a: { x: null, y: 1 } } ); apply_update_unchanged(test, "set key to undefined, was already undefined", { a: { y: 1, x: undefined } }, { a: { x: { '$set': undefined } } } ); apply_update_unchanged(test, "set key to null, was already null", { a: { y: 1, x: null } }, { a: { x: { '$set': null } } } ); apply_update(test, "editing an update with update", { a: { $set: 1 } }, { a: { $$set: { $set: 2 } } }, { a: { $set: 2 } } ); apply_update(test, "editing an update with update, nested key", { a: { $set: { b: 1 } } }, { a: { $$set: { b: { $set: 2 } } } }, { a: { $set: { b: 2 } } } ); // unset apply_update(test, "unset", { a: { b: 1, z: 2 }, c: 2 }, { a: { '$unset': 'b' } }, { a: { z: 2 }, c: 2 } ); apply_update(test, "unset multiple keys", { a: { b: 1, z: 2, x: 3, y: 4 }, c: 2 }, { a: { '$unset': ['b', 'z', 'y'] } }, { a: { x: 3 }, c: 2 } ); apply_update(test, "unset multiple keys, one doesn't exist", { a: { b: 1, z: 2, x: 3, y: 4 }, c: 2 }, { a: { '$unset': ['b', 'q', 'y'] } }, { a: { z: 2, x: 3 }, c: 2 } ); apply_update(test, "unset auto-vivify", {}, { a: { '$unset': 'b' } }, { a: {} } ); // merge apply_update(test, "merge", { a: 1, b: 2 }, { '$merge': { c: 3, d: { e: 4 } } }, { a: 1, b: 2, c: 3, d: { e: 4 } } ); apply_update(test, "merge overwrites", { a: 1, b: 2, c: 9 }, { '$merge': { c: 3, d: { e: 4 } } }, { a: 1, b: 2, c: 3, d: { e: 4 } } ); apply_update(test, "merge auto-vivify", { a: 1, b: 2 }, { q: { $merge: { b: 3, c: 4 } } }, { a: 1, b: 2, q: { b: 3, c: 4 } } ); apply_update(test, "merge undefined", { a: 1, b: 2 }, { '$merge': { c: undefined } }, { a: 1, b: 2, c: undefined } ); // push apply_update(test, "push", { a: [ 0, ], }, { a: { '$push': [ 1, 2 ] } }, { a: [ 0, 1, 2 ] } ); apply_update(test, "push auto-vivify", {}, { a: { '$push': [ 1, 2 ] } }, { a: [ 1, 2 ] } ); apply_update(test, "push auto-vivify null", { a: { b: null } }, { a: { b: { '$push': [ 1, 2 ] } } }, { a: { b: [ 1, 2 ] } } ); { let input = { items: [ "a", "b" ] }; input.items.top = 0; let output = { items: [ "a", "b", "c" ] }; output.items.top = 0; apply_update(test, "push, non-numeric keys are preserved", input, { items: { '$push': ["c"] } }, output ); } // unshift apply_update(test, "unshift", { a: [ 0 ] }, { a: { '$unshift': [ 1, 2 ] } }, { a: [ 1, 2, 0 ] } ); apply_update(test, "unshift auto-vivify", {}, { a: { '$unshift': [ 1, 2 ] } }, { a: [ 1, 2 ] } ); { let input = { items: [ "a", "b" ] }; input.items.top = 0; let output = { items: [ "c", "a", "b" ] }; output.items.top = 0; apply_update(test, "unshift, non-numeric keys are preserved", input, { items: { '$unshift': ["c"] } }, output ); } // splice apply_update(test, "splice add", { a: [ 0, 1 ], }, { a: { '$splice': [ [ 1, 0, 8, 9 ] ] } }, { a: [ 0, 8, 9, 1 ] } ); apply_update(test, "splice del", { a: [ 0, 1, 2 ] }, { a: { '$splice': [ [ 1, 1, 8, 9 ] ] } }, { a: [ 0, 8, 9, 2 ] } ); apply_update(test, "splice multi", { a: [ 0, 1, 2 ] }, { a: { '$splice': [ [ 1, 1, 8, 9 ], [ 0, 2, 6, {a: 1} ] ] } }, { a: [ 6, { a: 1 }, 9, 2 ] } ); apply_update(test, "splice auto-vivify", {}, { a: { '$splice': [ [ 0, 0, 8, 9 ] ] } }, { a: [ 8, 9 ] } ); // apply apply_update(test, "apply", { a: { b: 3, z: 2 }, c: 2 }, { a: { b: { '$apply': function(val) { return val * 2 } } } }, { a: { b: 6, z: 2 }, c: 2 } ); apply_update(test, "apply, auto-vivify", { c: 2 }, { a: { b: { '$apply': function(val) { test.deepEqual(val, undefined, "$apply value not autovified as undefined"); return 5 } } } }, { a: { b: 5 }, c: 2 } ); apply_update(test, "apply, auto-vivify null", { a: { b: null }, c: 2 }, { a: { b: { '$apply': function(val) { test.deepEqual(val, null, "$apply value not null as expected"); return 5 } } } }, { a: { b: 5 }, c: 2 } ); apply_update(test, "apply array", { a: [ 2 ] }, { a: { 0: { '$apply': function(val) { return val * 2 } } } }, { a: [ 4 ] } ); // Retain shallow equality apply_update_unchanged(test, "simple set, no update", { a: 1 }, { a: { $set: 1} } ); apply_update_unchanged(test, "nested set, no update", { a: { b: 1 }, c: 2 }, { a: { b: { '$set': 1 } } } ); apply_update_unchanged(test, "set array, no update", { a: [ 9, ], }, { a: { 0: { '$set': 9 } } } ); apply_update_unchanged(test, "unset but already unset", { a: { b: 1 } }, { a: { '$unset': 'c' } } ); apply_update_unchanged(test, "unset multiple but already unset", { a: { b: 1 } }, { a: { '$unset': ['c', 'd'] } } ); apply_update_unchanged(test, "unset none", { a: { b: 1 } }, { a: { '$unset': [] } } ); apply_update_unchanged(test, "push empty array", { a: { b: [1, 2, 3] } }, { a: { b: { '$push': [] } } } ); apply_update_unchanged(test, "unshift empty array", { a: { b: [1, 2, 3] } }, { a: { b: { '$unshift': [] } } } ); apply_update_unchanged(test, "apply unchanged", { a: { b: 0, z: 2 }, c: 2 }, { a: { b: { '$apply': function(val) { return val * 2 } } } } ); apply_update_unchanged(test, "merge unchanged", { a: 1, b: 2 }, { $merge: { b: 2 } } ); apply_update_unchanged(test, "merge unchanged", { a: 1, b: 2 }, { $merge: {} } ); // misc // https://github.com/kolodny/immutability-helper/issues/21 apply_update(test, "merge auto-vivfy 2.1", { items: {} }, { items: { 15: { '$merge': { 1: { id: 1, name: 'One' }, 2: { id: 2, name: 'Two'} } } } }, { items: { 15: { 1: { id: 1, name: 'One' }, 2: { id: 2, name: 'Two'} } } } ); apply_update(test, "merge auto-vivfy 2.2", { items: { 15: { 1: { id: 1, name: 'One' }, 2: { id: 2, name: 'Two'} } } }, { items: { 15: { '$merge': { 3: { id: 3, name: 'Three' } } } } }, { items: { 15: { 1: { id: 1, name: 'One' }, 2: { id: 2, name: 'Two'}, 3: { id: 3, name: 'Three' } } } } ); // multi-set apply_update(test, "multiple modifications in a single update", { a: { b: 1 } }, { c: { '$set': 2 }, a: { '$merge': { e: 3 } } }, { a: { b: 1, e: 3 }, c: 2 } ); apply_update(test, "unset same-level recursion", { a: 1 }, { $unset: 'a', b: { $set: 2 } }, { b: 2 } ); apply_update(test, "unset same-level recursion 2", { a: { b: 1 }, c: [2] }, { c: { $splice: [ [ 0, 1 ] ] }, $unset: 'a' }, { c: [], } ); apply_update(test, "unset same-level recursion 3", { a: { b: 1 }, c: [2] }, { c: { $set: 'dog' }, $unset: 'a' }, { c: 'dog', } ); apply_update(test, "unset same-level recursion 4", { a: { b: 1 }, c: [2] }, { a: { $unset: 'b' }, $unset: 'c' }, { a: {}, } ); apply_update(test, "merge same-level recursion", { a: 1, b: 2, c: 9 }, { '$merge': { c: 3, d: { e: 4 } }, test: { $set: 123 } }, { a: 1, b: 2, c: 3, d: { e: 4 }, test: 123 } ); apply_update(test, "merge and unset same-level recursion", { a: 1, b: 2, c: 9 }, { '$merge': { c: 3, d: { e: 4 } }, test: { $set: 123 }, $unset: 'a', }, { b: 2, c: 3, d: { e: 4 }, test: 123 } ); apply_update(test, "unset with auto-vivify at same-level of recursion", { a: 1 }, { $unset: 'a', b: { c: { $set: 2 } } }, { b: { c: 2 } } ); test.done(); };