immutable-ops
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -25,2 +25,6 @@ 'use strict'; | ||
var _ramdaSrcWrap = require('ramda/src/wrap'); | ||
var _ramdaSrcWrap2 = _interopRequireDefault(_ramdaSrcWrap); | ||
var _ramdaSrc__ = require('ramda/src/__'); | ||
@@ -100,3 +104,3 @@ | ||
var newObj = {}; | ||
prepareNewObject(newObj); | ||
prepareNewObject(opts, newObj); | ||
acc[curr] = newObj; | ||
@@ -260,6 +264,2 @@ return newObj; | ||
if (hasChanges) { | ||
addCanMutateTag(opts, nextObject); | ||
} | ||
return nextObject; | ||
@@ -338,3 +338,2 @@ } | ||
var vals = forceArray(_vals); | ||
var newArr = arr.slice(); | ||
@@ -348,3 +347,3 @@ prepareNewObject(opts, newArr); | ||
function immutableArrInsert(opts, index, _vals, arr) { | ||
if (canMutate(arr)) return mutableArrInsert(index, _vals, arr); | ||
if (canMutate(arr)) return mutableArrInsert(opts, index, _vals, arr); | ||
return immutableArrSplice(opts, index, 0, _vals, arr); | ||
@@ -462,9 +461,15 @@ } | ||
boundOperations.batched = function (func) { | ||
function batchWrapper() { | ||
var func = arguments[0]; | ||
var args = Array.prototype.slice.call(arguments, 1); | ||
opts.open(); | ||
var returnValue = func(); | ||
var returnValue = func.apply(null, args); | ||
opts.close(); | ||
return returnValue; | ||
}; | ||
} | ||
boundOperations.batched = batchWrapper; | ||
boundOperations.batch = (0, _ramdaSrcWrap2['default'])(_ramdaSrc__2['default'], batchWrapper); | ||
boundOperations.mutatedObjects = opts.mutatedObjects; | ||
@@ -471,0 +476,0 @@ |
@@ -17,2 +17,10 @@ 'use strict'; | ||
var _deepFreeze = require('deep-freeze'); | ||
var _deepFreeze2 = _interopRequireDefault(_deepFreeze); | ||
var _ramdaSrcCompose = require('ramda/src/compose'); | ||
var _ramdaSrcCompose2 = _interopRequireDefault(_ramdaSrcCompose); | ||
_chai2['default'].use(_sinonChai2['default']); | ||
@@ -28,6 +36,18 @@ var expect = _chai2['default'].expect; | ||
it('wrapBatched', function () { | ||
var pushFour = ops.push(4); | ||
var pushFive = ops.push(5); | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 3]); | ||
var pusher = ops.batch((0, _ramdaSrcCompose2['default'])(pushFive, pushFour)); | ||
expect(pusher).to.be.a('function'); | ||
var result = pusher(arr); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
describe('object', function () { | ||
describe('batched mutations', function () { | ||
it('deepMerges', function () { | ||
var baseObj = { | ||
var baseObj = (0, _deepFreeze2['default'])({ | ||
change: 'Tommi', | ||
@@ -39,4 +59,4 @@ dontChange: 25, | ||
} | ||
}; | ||
var mergeObj = { | ||
}); | ||
var mergeObj = (0, _deepFreeze2['default'])({ | ||
change: 'None', | ||
@@ -48,3 +68,3 @@ add: 'US', | ||
} | ||
}; | ||
}); | ||
var result = undefined; | ||
@@ -74,6 +94,6 @@ var merger = ops.deepMerge(mergeObj); | ||
it('omits a single key', function () { | ||
var obj = { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
name: 'Tommi', | ||
age: 25 | ||
}; | ||
}); | ||
@@ -93,6 +113,6 @@ var result = undefined; | ||
it('omits an array of keys', function () { | ||
var obj = { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
name: 'Tommi', | ||
age: 25 | ||
}; | ||
}); | ||
@@ -113,3 +133,3 @@ var result = undefined; | ||
it('sets a value in path', function () { | ||
var obj = { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
first: { | ||
@@ -123,3 +143,3 @@ second: { | ||
maintain: true | ||
}; | ||
}); | ||
var result = undefined; | ||
@@ -143,2 +163,90 @@ | ||
}); | ||
describe('immutable ops', function () { | ||
it('deepMerges', function () { | ||
var baseObj = (0, _deepFreeze2['default'])({ | ||
change: 'Tommi', | ||
dontChange: 25, | ||
deeper: { | ||
dontChange: 'John', | ||
change: 30 | ||
} | ||
}); | ||
var mergeObj = (0, _deepFreeze2['default'])({ | ||
change: 'None', | ||
add: 'US', | ||
deeper: { | ||
add: 'US', | ||
change: 35 | ||
} | ||
}); | ||
var merger = ops.deepMerge(mergeObj); | ||
var result = merger(baseObj); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
expect((0, _index.canMutate)(result.deeper)).to.be['false']; | ||
expect(result).to.not.equal(baseObj); | ||
expect(result).to.contain.all.keys(['change', 'dontChange', 'add', 'deeper']); | ||
expect(result.change).to.not.equal(baseObj.change); | ||
expect(result.dontChange).to.equal(baseObj.dontChange); | ||
expect(result.deeper).to.not.equal(baseObj.deeper); | ||
expect(result.deeper).to.contain.all.keys(['dontChange', 'change', 'add']); | ||
expect(result.deeper.dontChange).to.equal(baseObj.deeper.dontChange); | ||
expect(result.deeper.change).to.not.equal(baseObj.deeper.change); | ||
}); | ||
it('omits a single key', function () { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
name: 'Tommi', | ||
age: 25 | ||
}); | ||
var omitter = ops.omit('age'); | ||
var result = omitter(obj); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
expect(result).to.not.contain.keys(['age']); | ||
}); | ||
it('omits an array of keys', function () { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
name: 'Tommi', | ||
age: 25 | ||
}); | ||
var omitter = ops.omit(['age']); | ||
var result = omitter(obj); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
expect(result).to.not.contain.keys(['age']); | ||
}); | ||
it('sets a value in path', function () { | ||
var obj = (0, _deepFreeze2['default'])({ | ||
first: { | ||
second: { | ||
value: 'value', | ||
maintain: true | ||
}, | ||
maintain: true | ||
}, | ||
maintain: true | ||
}); | ||
var setter = ops.setIn('first.second.value', 'anotherValue'); | ||
var result = setter(obj); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
expect(result).not.to.equal(obj); | ||
expect(result.first.second.value).to.equal('anotherValue'); | ||
expect(result.maintain).to.be['true']; | ||
expect(result.first.maintain).to.be['true']; | ||
expect(result.first.second.maintain).to.be['true']; | ||
}); | ||
}); | ||
}); | ||
@@ -150,4 +258,4 @@ | ||
var push = ops.push; | ||
var arr = [5, 4]; | ||
var pusher = push([1, 2, 3]); | ||
var arr = (0, _deepFreeze2['default'])([5, 4]); | ||
var pusher = push((0, _deepFreeze2['default'])([1, 2, 3])); | ||
var result = ops.batched(function () { | ||
@@ -164,4 +272,4 @@ return pusher(arr); | ||
var insert = ops.insert; | ||
var arr = [1, 2, 5]; | ||
var inserter = insert(2, [3, 4]); | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 5]); | ||
var inserter = insert(2, (0, _deepFreeze2['default'])([3, 4])); | ||
var result = ops.batched(function () { | ||
@@ -175,3 +283,3 @@ return inserter(arr); | ||
it('filter', function () { | ||
var arr = [0, 1, 2, 3]; | ||
var arr = (0, _deepFreeze2['default'])([0, 1, 2, 3]); | ||
var result = undefined; | ||
@@ -191,3 +299,3 @@ | ||
it('set', function () { | ||
var arr = [1, 2, 987, 4]; | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 987, 4]); | ||
@@ -207,5 +315,72 @@ var result = ops.batched(function () { | ||
var splice = ops.splice; | ||
var arr = [1, 2, 3, 3, 3, 4]; | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 3, 3, 3, 4]); | ||
var splicer = splice(2, 2, []); | ||
var result = ops.batched(function () { | ||
return splicer(arr); | ||
}); | ||
expect(result).to.deep.equal([1, 2, 3, 4]); | ||
}); | ||
it('splice with additions', function () { | ||
var splice = ops.splice; | ||
var arr = (0, _deepFreeze2['default'])([1, 5]); | ||
var splicer = splice(1, 0, [2, 3, 4]); | ||
var result = ops.batched(function () { | ||
return splicer(arr); | ||
}); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
}); | ||
describe('immutable ops', function () { | ||
it('push', function () { | ||
var push = ops.push; | ||
var arr = (0, _deepFreeze2['default'])([5, 4]); | ||
var pusher = push((0, _deepFreeze2['default'])([1, 2, 3])); | ||
var result = pusher(arr); | ||
expect(result).to.not.equal(arr); | ||
expect(result).to.deep.equal([5, 4, 1, 2, 3]); | ||
}); | ||
it('insert', function () { | ||
var insert = ops.insert; | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 5]); | ||
var inserter = insert(2, (0, _deepFreeze2['default'])([3, 4])); | ||
var result = inserter(arr); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
it('filter', function () { | ||
var arr = (0, _deepFreeze2['default'])([0, 1, 2, 3]); | ||
var result = ops.filter(function (item) { | ||
return item % 2 === 0; | ||
}, arr); | ||
expect(result).to.deep.equal([0, 2]); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
}); | ||
it('set', function () { | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 987, 4]); | ||
var setter = ops.set(2, 3); | ||
var result = setter(arr); | ||
expect((0, _index.canMutate)(result)).to.be['false']; | ||
expect(result).to.deep.equal([1, 2, 3, 4]); | ||
}); | ||
it('splice with deletions', function () { | ||
var splice = ops.splice; | ||
var arr = (0, _deepFreeze2['default'])([1, 2, 3, 3, 3, 4]); | ||
var splicer = splice(2, 2, []); | ||
var result = splicer(arr); | ||
@@ -217,3 +392,3 @@ expect(result).to.deep.equal([1, 2, 3, 4]); | ||
var splice = ops.splice; | ||
var arr = [1, 5]; | ||
var arr = (0, _deepFreeze2['default'])([1, 5]); | ||
var splicer = splice(1, 0, [2, 3, 4]); | ||
@@ -220,0 +395,0 @@ |
{ | ||
"name": "immutable-ops", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "A collection of functions to perform immutable operations on plain JavaScript objects", | ||
@@ -10,4 +10,3 @@ "main": "lib/index.js", | ||
}, | ||
"keywords": [ | ||
], | ||
"keywords": [], | ||
"author": "Tommi Kaikkonen <tommi.kaikkonen@aalto.fi>", | ||
@@ -24,2 +23,3 @@ "repository": { | ||
"chai": "^3.0.0", | ||
"deep-freeze": "0.0.1", | ||
"eslint": "^1.10.1", | ||
@@ -26,0 +26,0 @@ "eslint-config-airbnb": "1.0.0", |
immutable-ops | ||
=============== | ||
A collection of functions to perform immutable operations on plain JavaScript objects and arrays. Aims to have the simplicity and small size of `seamless-immutable`, but with a functional, curried API, no special immutable object type, and batched mutations. | ||
A collection of functions to perform immutable operations on plain JavaScript objects and arrays. | ||
Like [updeep](https://github.com/substantial/updeep) but with batched mutations and no freezing. | ||
Like [icepick](https://github.com/aearly/icepick), but with batched mutations and a curried API that puts the target object as the last argument. No freezing. | ||
## Features | ||
@@ -19,7 +23,7 @@ | ||
## Usage | ||
## Example Usage | ||
```javascript | ||
import compose from 'ramda/src/compose'; | ||
import getImmutableOps from 'immutable-ops'; | ||
import getOps from 'immutable-ops'; | ||
@@ -48,3 +52,3 @@ // These are all the available functions. | ||
__, | ||
} = getImmutableOps({ | ||
} = getOps({ | ||
// These are the default options. | ||
@@ -54,60 +58,25 @@ curried: true | ||
const person = { | ||
name: 'Tommi', | ||
age: 25, | ||
location: { | ||
city: 'New York', | ||
country: 'US', | ||
}, | ||
}; | ||
const arr = [1, 2, 3]; | ||
// All functions are curried. This returns a function that should be | ||
// called with the last argument, the object to be operated on. | ||
const moveToNY = mergeDeep({ location: { city: 'New York' }}); | ||
const moveToSF = mergeDeep({ location: { city: 'San Francisco' }}); | ||
const pushFour = ops.push(4); | ||
const pushFive = ops.push(5); | ||
const updatedPerson = moveToNY(person); | ||
// All functions are curried. These functions | ||
// still need the final argument, the array to | ||
// operate on. | ||
expect(pushFive).to.be.a('function'); | ||
// If any changes are not made, the same object is returned. | ||
updatedPerson === person | ||
// true | ||
const pushFourAndFive = compose(pushFive, pushFour); | ||
const becomeABanker = setIn('occupation.title', 'Investment Banker'); | ||
const advanceCareer = compose(becomeABanker, moveToNY) | ||
const result = pushFourAndFive(arr); | ||
// Two new arrays were created during `pushFourAndFive` eecution. | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
const personWithJob = advanceCareer(person); | ||
console.log(personWithJob === person); | ||
// false | ||
const batchedPushFourAndFive = ops.batch(pushFourAndFive); | ||
console.log(personWithJob); | ||
// { | ||
// name: 'Tommi', | ||
// age: 25, | ||
// location: { | ||
// city: 'New York', | ||
// country: 'US', | ||
// }, | ||
// occupation: { | ||
// title: 'Investment Banker', | ||
// } | ||
// } | ||
const runOperations = compose(advanceCareer, moveToSf); | ||
const personWithJobTwo = ops.batched(() => runOperations(person)); | ||
console.log(person === personWithJobTwo) | ||
// false | ||
// All data is still immutable. `ops.batched(() => runOperations(person))` returns a deeply equal result to the just running `runOperations(person)`. The difference is in the amount of objects created during `runOperations`. When `moveToSF` is first called, it creates a new object for the `location` key with the updated `city`. When `advanceCareer` calls `moveToNY`, that `location` object is mutated instead of a new one being created. | ||
console.log(personWithJobTwo); | ||
// { | ||
// name: 'Tommi', | ||
// age: 25, | ||
// location: { | ||
// city: 'New York', | ||
// country: 'US', | ||
// }, | ||
// occupation: { | ||
// title: 'Investment Banker', | ||
// } | ||
// } | ||
const sameResult = batchedPushFourAndFive(arr); | ||
// Only one new array is created during `batchedPushFourAndFive` execution. | ||
// `immutable-ops` keeps track of objects mutated during the wrapped | ||
// function, and applies the same operations with mutations to those objects. | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
``` | ||
@@ -117,3 +86,3 @@ | ||
You can batch operations by calling `ops.batched(func)` with a function. | ||
You can run operations in a mutation batch by calling `ops.batched(func)` with a function, and you can create a batch-wrapped function with `const batchedFunc = ops.batch(funcToWrap)`. | ||
@@ -124,2 +93,4 @@ When `immutable-ops` creates a new object or array during batched mutations to preserve immutability, it tags it as a mutable object (by adding an unenumerable `@@_____canMutate` property) and pushes its reference to an array of `mutatedObjects`. All consecutive functions applied will execute a mutating operations for objects that have the tag. This applies for tagged objects found in nested structures too. | ||
The overhead of keeping track of mutated objects should be a sufficient tradeoff to creating lots of new objects to applyi multiple consecutive operations, unless you're working on a really big set of data. | ||
## Currying | ||
@@ -138,2 +109,12 @@ | ||
## Batched Mutations API | ||
### batched(functionToRun) | ||
Executes `functionToRun` as a batched mutation and returns the return value of `functionToRun`.`functionToRun` will be called without arguments. During `functionToRun` execution, `immutable-ops` will keep track of new objects created during operations, and apply further operations with mutations to those objects. | ||
### batch(functionToWrap) | ||
Like `batched`, but returns a function that wraps `functionToWrap` to be executed as a batch. `functionToWrap` is also curried. When `functionToWrap` is executed (all arguments are passed), all operations run during its execution will apply mutations instead of creating new objects whenever possible. | ||
## Object API | ||
@@ -140,0 +121,0 @@ |
import forOwn from 'lodash/forOwn'; | ||
import isArrayLike from 'lodash/isArrayLike'; | ||
import curry from 'ramda/src/curry'; | ||
import wrap from 'ramda/src/wrap'; | ||
import placeholder from 'ramda/src/__'; | ||
@@ -76,3 +77,3 @@ | ||
const newObj = {}; | ||
prepareNewObject(newObj); | ||
prepareNewObject(opts, newObj); | ||
acc[curr] = newObj; | ||
@@ -238,6 +239,2 @@ return newObj; | ||
if (hasChanges) { | ||
addCanMutateTag(opts, nextObject); | ||
} | ||
return nextObject; | ||
@@ -316,3 +313,2 @@ } | ||
const vals = forceArray(_vals); | ||
const newArr = arr.slice(); | ||
@@ -326,3 +322,3 @@ prepareNewObject(opts, newArr); | ||
function immutableArrInsert(opts, index, _vals, arr) { | ||
if (canMutate(arr)) return mutableArrInsert(index, _vals, arr); | ||
if (canMutate(arr)) return mutableArrInsert(opts, index, _vals, arr); | ||
return immutableArrSplice(opts, index, 0, _vals, arr); | ||
@@ -440,9 +436,15 @@ } | ||
boundOperations.batched = func => { | ||
function batchWrapper() { | ||
const func = arguments[0]; | ||
const args = Array.prototype.slice.call(arguments, 1); | ||
opts.open(); | ||
const returnValue = func(); | ||
const returnValue = func.apply(null, args); | ||
opts.close(); | ||
return returnValue; | ||
}; | ||
} | ||
boundOperations.batched = batchWrapper; | ||
boundOperations.batch = wrap(placeholder, batchWrapper); | ||
boundOperations.mutatedObjects = opts.mutatedObjects; | ||
@@ -449,0 +451,0 @@ |
import chai from 'chai'; | ||
import sinonChai from 'sinon-chai'; | ||
import getOps, { canMutate } from '../index'; | ||
import freeze from 'deep-freeze'; | ||
import compose from 'ramda/src/compose'; | ||
@@ -15,6 +17,18 @@ chai.use(sinonChai); | ||
it('wrapBatched', () => { | ||
const pushFour = ops.push(4); | ||
const pushFive = ops.push(5); | ||
const arr = freeze([1, 2, 3]); | ||
const pusher = ops.batch(compose(pushFive, pushFour)); | ||
expect(pusher).to.be.a('function'); | ||
const result = pusher(arr); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
describe('object', () => { | ||
describe('batched mutations', () => { | ||
it('deepMerges', () => { | ||
const baseObj = { | ||
const baseObj = freeze({ | ||
change: 'Tommi', | ||
@@ -26,4 +40,4 @@ dontChange: 25, | ||
}, | ||
}; | ||
const mergeObj = { | ||
}); | ||
const mergeObj = freeze({ | ||
change: 'None', | ||
@@ -35,3 +49,3 @@ add: 'US', | ||
}, | ||
}; | ||
}); | ||
let result; | ||
@@ -61,6 +75,6 @@ const merger = ops.deepMerge(mergeObj); | ||
it('omits a single key', () => { | ||
const obj = { | ||
const obj = freeze({ | ||
name: 'Tommi', | ||
age: 25, | ||
}; | ||
}); | ||
@@ -80,6 +94,6 @@ let result; | ||
it('omits an array of keys', () => { | ||
const obj = { | ||
const obj = freeze({ | ||
name: 'Tommi', | ||
age: 25, | ||
}; | ||
}); | ||
@@ -100,3 +114,3 @@ let result; | ||
it('sets a value in path', () => { | ||
const obj = { | ||
const obj = freeze({ | ||
first: { | ||
@@ -110,3 +124,3 @@ second: { | ||
maintain: true, | ||
}; | ||
}); | ||
let result; | ||
@@ -130,2 +144,90 @@ | ||
}); | ||
describe('immutable ops', () => { | ||
it('deepMerges', () => { | ||
const baseObj = freeze({ | ||
change: 'Tommi', | ||
dontChange: 25, | ||
deeper: { | ||
dontChange: 'John', | ||
change: 30, | ||
}, | ||
}); | ||
const mergeObj = freeze({ | ||
change: 'None', | ||
add: 'US', | ||
deeper: { | ||
add: 'US', | ||
change: 35, | ||
}, | ||
}); | ||
const merger = ops.deepMerge(mergeObj); | ||
const result = merger(baseObj); | ||
expect(canMutate(result)).to.be.false; | ||
expect(canMutate(result.deeper)).to.be.false; | ||
expect(result).to.not.equal(baseObj); | ||
expect(result).to.contain.all.keys(['change', 'dontChange', 'add', 'deeper']); | ||
expect(result.change).to.not.equal(baseObj.change); | ||
expect(result.dontChange).to.equal(baseObj.dontChange); | ||
expect(result.deeper).to.not.equal(baseObj.deeper); | ||
expect(result.deeper).to.contain.all.keys(['dontChange', 'change', 'add']); | ||
expect(result.deeper.dontChange).to.equal(baseObj.deeper.dontChange); | ||
expect(result.deeper.change).to.not.equal(baseObj.deeper.change); | ||
}); | ||
it('omits a single key', () => { | ||
const obj = freeze({ | ||
name: 'Tommi', | ||
age: 25, | ||
}); | ||
const omitter = ops.omit('age'); | ||
const result = omitter(obj); | ||
expect(canMutate(result)).to.be.false; | ||
expect(result).to.not.contain.keys(['age']); | ||
}); | ||
it('omits an array of keys', () => { | ||
const obj = freeze({ | ||
name: 'Tommi', | ||
age: 25, | ||
}); | ||
const omitter = ops.omit(['age']); | ||
const result = omitter(obj); | ||
expect(canMutate(result)).to.be.false; | ||
expect(result).to.not.contain.keys(['age']); | ||
}); | ||
it('sets a value in path', () => { | ||
const obj = freeze({ | ||
first: { | ||
second: { | ||
value: 'value', | ||
maintain: true, | ||
}, | ||
maintain: true, | ||
}, | ||
maintain: true, | ||
}); | ||
const setter = ops.setIn('first.second.value', 'anotherValue'); | ||
const result = setter(obj); | ||
expect(canMutate(result)).to.be.false; | ||
expect(result).not.to.equal(obj); | ||
expect(result.first.second.value).to.equal('anotherValue'); | ||
expect(result.maintain).to.be.true; | ||
expect(result.first.maintain).to.be.true; | ||
expect(result.first.second.maintain).to.be.true; | ||
}); | ||
}); | ||
}); | ||
@@ -137,4 +239,4 @@ | ||
const push = ops.push; | ||
const arr = [5, 4]; | ||
const pusher = push([1, 2, 3]); | ||
const arr = freeze([5, 4]); | ||
const pusher = push(freeze([1, 2, 3])); | ||
const result = ops.batched(() => pusher(arr)); | ||
@@ -149,4 +251,4 @@ | ||
const insert = ops.insert; | ||
const arr = [1, 2, 5]; | ||
const inserter = insert(2, [3, 4]); | ||
const arr = freeze([1, 2, 5]); | ||
const inserter = insert(2, freeze([3, 4])); | ||
const result = ops.batched(() => inserter(arr)); | ||
@@ -158,3 +260,3 @@ | ||
it('filter', () => { | ||
const arr = [0, 1, 2, 3]; | ||
const arr = freeze([0, 1, 2, 3]); | ||
let result; | ||
@@ -172,3 +274,3 @@ | ||
it('set', () => { | ||
const arr = [1, 2, 987, 4]; | ||
const arr = freeze([1, 2, 987, 4]); | ||
@@ -188,5 +290,66 @@ const result = ops.batched(() => { | ||
const splice = ops.splice; | ||
const arr = [1, 2, 3, 3, 3, 4]; | ||
const arr = freeze([1, 2, 3, 3, 3, 4]); | ||
const splicer = splice(2, 2, []); | ||
const result = ops.batched(() => splicer(arr)); | ||
expect(result).to.deep.equal([1, 2, 3, 4]); | ||
}); | ||
it('splice with additions', () => { | ||
const splice = ops.splice; | ||
const arr = freeze([1, 5]); | ||
const splicer = splice(1, 0, [2, 3, 4]); | ||
const result = ops.batched(() => splicer(arr)); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
}); | ||
describe('immutable ops', () => { | ||
it('push', () => { | ||
const push = ops.push; | ||
const arr = freeze([5, 4]); | ||
const pusher = push(freeze([1, 2, 3])); | ||
const result = pusher(arr); | ||
expect(result).to.not.equal(arr); | ||
expect(result).to.deep.equal([5, 4, 1, 2, 3]); | ||
}); | ||
it('insert', () => { | ||
const insert = ops.insert; | ||
const arr = freeze([1, 2, 5]); | ||
const inserter = insert(2, freeze([3, 4])); | ||
const result = inserter(arr); | ||
expect(result).to.deep.equal([1, 2, 3, 4, 5]); | ||
}); | ||
it('filter', () => { | ||
const arr = freeze([0, 1, 2, 3]); | ||
const result = ops.filter(item => item % 2 === 0, arr); | ||
expect(result).to.deep.equal([0, 2]); | ||
expect(canMutate(result)).to.be.false; | ||
}); | ||
it('set', () => { | ||
const arr = freeze([1, 2, 987, 4]); | ||
const setter = ops.set(2, 3); | ||
const result = setter(arr); | ||
expect(canMutate(result)).to.be.false; | ||
expect(result).to.deep.equal([1, 2, 3, 4]); | ||
}); | ||
it('splice with deletions', () => { | ||
const splice = ops.splice; | ||
const arr = freeze([1, 2, 3, 3, 3, 4]); | ||
const splicer = splice(2, 2, []); | ||
const result = splicer(arr); | ||
@@ -198,3 +361,3 @@ expect(result).to.deep.equal([1, 2, 3, 4]); | ||
const splice = ops.splice; | ||
const arr = [1, 5]; | ||
const arr = freeze([1, 5]); | ||
const splicer = splice(1, 0, [2, 3, 4]); | ||
@@ -201,0 +364,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
61504
1318
10
301