New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mongo-dot-notation

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongo-dot-notation - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

lib/array.js

17

index.js
'use strict';
var fieldOperators = require('./lib/fields');
module.exports.isOperator = require('./lib/operator').isOperator;
module.exports.flatten = require('./lib/flatten');
// copy all field operators
Object.keys(fieldOperators).forEach(function(operator){
module.exports[operator] = fieldOperators[operator];
});
extend(require('./lib/field'));
extend(require('./lib/array'));
extend(require('./lib/bitwise'));

@@ -16,2 +13,8 @@ /*

*/
module.exports.Operators = fieldOperators;
module.exports.Operators = require('./lib/field');
function extend(operators){
Object.keys(operators).forEach(function(operatorName){
module.exports[operatorName] = operators[operatorName];
});
}
'use strict';
var util = require('util');
var isOperator = require('./operator').isOperator;
var Operator = require('./operator');

@@ -39,3 +39,3 @@ var PrimitiveTypes = [

if (isOperator(propertyValue)) {
if (Operator.isOperator(propertyValue)) {
return build(updateData, propertyValue.name,

@@ -61,5 +61,8 @@ propertyName, propertyValue.value());

function build(updateData, operator, propertyName, value) {
if (Operator.isOperator(value))
return build(updateData, value.name, propertyName + '.' + operator, value.value());
updateData[operator] = updateData[operator] || {};
updateData[operator][propertyName] = value;
return updateData;

@@ -66,0 +69,0 @@ }

'use strict';
module.exports = Operator;
function Operator(name){
if (!name)
throw new Error('Null argument error: name');
this.name = name;

@@ -15,3 +19,7 @@ }

module.exports.create = function(name){ return new Operator(name); };
module.exports.isOperator = function(obj){ return obj && obj instanceof Operator; };
Operator.isOperator = function(obj){ return obj && obj instanceof Operator; };
Operator.create = function(name, value, defaultValue){
var operator = new Operator(name);
operator.value(typeof(value) === 'undefined' ? defaultValue : value);
return operator;
};
{
"name": "mongo-dot-notation",
"version": "1.1.0",
"description": "Convert simple objects to mongo update operators",
"version": "1.2.0",
"description": "Transform objects to mongo update instructions",
"author": {

@@ -17,5 +17,8 @@ "name": "Dumitru Deveatii",

"mongo",
"dot",
"dot-notation",
"conversion",
"transform",
"convert",
"operators",
"instructions",
"json",

@@ -25,3 +28,4 @@ "objects",

"data",
"flatten"
"flatten",
"update"
],

@@ -33,3 +37,5 @@ "license": "MIT",

"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly",
"lint": "eslint lib"
"coverage": "istanbul cover node_modules/mocha/bin/_mocha --report html",
"lint": "eslint lib",
"perf": "node ./test/performance.js"
},

@@ -42,4 +48,4 @@ "devDependencies": {

"mocha-lcov-reporter": "^1.3.0",
"mongodb": "^2.2.27"
"mongodb": "^2.2.28"
}
}
mongo-dot-notation
========
Convert simple objects to mongo update operators. <br/>
Fast, lightweight library to transform objects to mongo update instructions using operators.

@@ -9,223 +9,629 @@ [![NPM Version](https://img.shields.io/npm/v/mongo-dot-notation.svg)](https://npmjs.org/package/mongo-dot-notation)

This lightweight library can be used to create a more readable code when working with mongo updates.
You focus on updated properties of the document, rather than on mongo update instructions.
##### Example:
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/mydatabase';
MongoClient.connect(url, function(err, db) {
if (err) throw err;
// standard way
var update = {
$set: {
'comment': 'Logged in.',
'system': 'demo',
'account.attempts': 0
},
$currentDate: {
'login.date': true
},
$inc: {
'analytics.visits': 1,
'account.logins': 1,
},
$unset: {
'account.blocked'
}
}
updateUser(db, update, function(err, res){
db.close();
})
// using mongo-dot-notation
var update = {
comment: 'Logged in.',
system: 'demo',
login: {
date: $.$currentDate()
},
analytics: {
visits: $.$inc()
},
account: {
blocked: $.$unset(),
attempts: 0,
logins: $.$inc()
}
var instructions = $.flatten({
firstName: 'John',
contact: { phone: '874-478-1254' },
lastUpdate: $.$currentDate()
})
/*
var instructions = {
$currentDate: {
lastUpdate: { $type: 'date' }
},
$set: {
'firstName': 'John',
'contact.phone': '874-478-1254'
}
updateUser(db, $.flatten(update), function(err, res){
db.close();
}
*/
```
## Installation
```bash
$ npm install mongo-dot-notation --save
```
## Features
* Transform objects to mongo update instructions
* supports embedded documents
* understands mongo types (ObjectID, Int32 etc.)
* Full support of mongo update operators
* Field update operators
* Array update operators
* Bitwise update operators
* Compatible with node >= 0.12
* No *npm* dependencies on mongo
## Usage
Using `$.flatten` and operators to transform to mongo update instructions.
```javascript
var $ = require('mongo-dot-notation')
var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/mydatabase'
MongoClient.connect(url).then(function(db) {
return db.collection('users').update(
{ _id: 1 },
$.flatten({
comments: $.$push('Logged in.').$each().$slice(-100),
env: 'demo',
login: {
date: $.$currentDate()
},
analytics: {
visits: $.$inc()
},
account: {
createdOn: $.$setOnInsert(new Date()),
blocked: $.$unset(),
attempts: 0,
logins: $.$inc()
}
})
})
});
```
function updateUser(db, user, handler){
var collection = db.collection('users');
collection.update({username: 'johndoe@test.com'}, user, handler);
}
Without `mongo-dot-notation` update instructions should look like:
``` javascript
...
return collection.update(
{ _id: 1 },
{
$set: {
'env': 'demo',
'account.attempts': 0
},
$push: {
'comments': {
'$each': ['Logged in.'],
'$slice': -100
}
}
$currentDate: {
'login.date': 'date'
},
$inc: {
'analytics.visits': 1,
'account.logins': 1,
},
$unset: {
'account.blocked': ''
},
$setOnInsert: {
'account.createdOn': new Date()
}
})
})
```
The current implementation supports all mongo update operators:
* $inc
* $mul
* $rename
* $setOnInsert
* $set
* $unset
* $min
* $max
* $currentDate
* use $currentDate for conversion to $type = 'date'
* use $timestamp for conversion to $type = 'timestamp'
## Tests
### Installation
To run the test suite make sure you have mongo 2.6+ installed locally on the default port (*27017*).
Mongo is used to run integration tests.
Once mongo is available, install the dependencies, then run `npm test`:
Install from npm:
```bash
$ npm install
$ npm test
```
npm install mongo-dot-notation --save
To calculate code coverage run `npm run-script test-ci`.
## API
## `.flatten()`
Use `.flatten()` to transform objects:
```javascript
var $ = require('mongo-dot-notation')
var instructions = $.flatten({
account: {
name: 'hero'
}
})
// { '$set': { 'account.name': 'hero' } }
```
## Usage
### Convert a simple object
## `.isOperator()`
Checks if a given value is a `mongo-dot-notation` operator:
```javascript
var $ = require('mongo-dot-notation')
$.isOperator(1) // false
$.isOperator({}) // false
$.isOperator($.$set(10)) // true
```
See below the list of all supported mongo update opertors.
## Mongo update operators
### Field update operators
#### `.$inc`
See mongo [**$inc**](https://docs.mongodb.com/manual/reference/operator/update/inc/).
The `$inc` operator increments a field by a specified value. If no value is provided, defaults to 1.
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
$.flatten({
visits: $.$inc(5) // increment current visits value by 5
})
// { '$inc': { 'visits': 5 } }
```
var person = {
firstName: 'John',
lastName: 'Doe'
};
#### `.$mul`
See mongo [**$mul**](https://docs.mongodb.com/manual/reference/operator/update/mul/).
var instructions = $.flatten(person)
console.log(instructions);
/*
{
$set: {
'firstName': 'John',
'lastName': 'Doe'
}
}
*/
Multiplies the value of a field by a number. (*Supported in mongo >= 2.6*)
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
price: $.$mul(0.75) // multiply current price value by 0.75
})
// { '$mul': { 'price': 0.75 } }
```
### Convert an object with deep properties
#### `.$rename`
See mongo [**$rename**](https://docs.mongodb.com/manual/reference/operator/update/rename/).
The `$rename` operator updates the name of a field.
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
$.flatten({
nmae: $.$rename('name') // rename nmae field to name
})
// { '$rename': { 'nmae': 'name' } }
```
var person = {
firstName: 'John',
lastName: 'Doe',
address: {
city: 'NY',
street: 'Eighth Avenu',
number: 123
#### `.$setOnInsert`
See mongo [**$setOnInsert**](https://docs.mongodb.com/manual/reference/operator/update/setOnInsert/).
Assigns value to field only when the document is inserted (when an update operation is with `upsert:true`). (*Supported in mongo >= 2.4*)
```javascript
var $ = require('mongo-dot-notation')
db.collection('users').update(
{ _id: 1 },
$.flatten({
createdOn: $.$setOnInsert(new Date()) // sets createdOn field only when document is inserted
}),
{ upsert: true })
// { '$setOnInsert': { 'createdOn': new Date() } }
```
#### `.$set`
See mongo [**$set**](https://docs.mongodb.com/manual/reference/operator/update/set/).
The `$set` operator replaces the value of a field with the specified value.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
name: $.$set('Mike')
})
// { '$set': { 'name': 'Mike' } }
```
The `$set` is an implicit operator, meaning if an object is passed to `$.flatten`, it will navigate through own and embedded document fields and apply $set.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
name: 'Mike',
contactDetails: {
email: 'mike@test.com'
}
};
})
var instructions = $.flatten(person)
console.log(instructions);
/*
{
$set: {
'firstName': 'John',
'lastName': 'Doe',
'address.city': 'NY',
'address.street': 'Eighth Avenu',
'address.number': 123
}
}
*/
// {
// '$set': {
// 'name': 'Mike',
// 'contactDetails.email': 'mike@test.com'
// }
// }
```
### Using operators
The `$set` operator could also be used to update an embedded document entirely:
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
$.flatten({
name: 'Mike',
// contactDetails is updated to a new document
contactDetails: $.$set({
email: 'mike@test.com'
})
})
var person = {
password: '1234',
updated: $.$currentDate(),
resetCounter: $.$inc()
};
// {
// '$set': {
// 'name': 'Mike',
// 'contactDetails': { email: 'mike@test.com' }
// }
// }
```
var instructions = $.flatten(person)
console.log(instructions);
/*
{
$set: {
'password': '1234'
},
$inc: {
'resetCounter': 1
},
$currentDate: {
'updated': { $type: 'date'},
}
}
*/
#### `.$unset`
See mongo [**$unset**](https://docs.mongodb.com/manual/reference/operator/update/unset/).
The `$unset` operator deletes a particular field.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
comments: $.$unset(), // remove field from document
history: $.$unset()
})
// { '$unset': { 'comments': '', 'history': '' } }
```
Operators can also be used in inner objects:
#### `.$min`
See mongo [**$min**](https://docs.mongodb.com/manual/reference/operator/update/min/).
The `$min` updates the value of the field to a specified value if the specified value is less than the current value of the field.
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
$.flatten({
low: $.$min(200) // update low to 200 if current low value is greater than 200
})
// { '$min': { 'low': 200 } }
```
var pos = {
coords: {
x: $.$mul(2),
y: $.$inc(10),
z: $.$unset(),
mark: [1, 2, 3]
},
label: $.$rename('title')
};
#### `.$max`
See mongo [$max](https://docs.mongodb.com/manual/reference/operator/update/max/).
var instructions = $.flatten(pos)
console.log(instructions);
/*
{
$set: {
'coords.mark': [1, 2, 3]
},
$mul: {
'coords.x': 2
},
$inc: {
'coords.y': 10
},
$unset: {
'coords.z': ''
},
$rename: {
'label': 'title'
}
}
*/
The `$max` operator updates the value of the field to a specified value if the specified value is greater than the current value of the field.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
high: $.$max(450) // update high to 450 if current high value is less than 450
})
// { '$max': { 'high': 450 } }
```
Operators cannot be used inside arrays.
#### `.$currentDate`
See mongo [**$currentDate**](https://docs.mongodb.com/manual/reference/operator/update/currentDate/).
## Update operators signatures
The `$currentDate` operator sets the value of a field to the current date, either as a *Date* or a *Timestamp*.
If type is not specified, uses *Date* by default.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
lastUpdate: $.$currentDate()
})
// { '$currentDate': { 'lastUpdated': { '$type': 'date' } } }
```
See [MongoDB - Fields update operators](https://docs.mongodb.com/manual/reference/operator/update/#fields).
To set as a timestamp, use:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
lastUpdate: $.$currentDate('timestamp')
})
// { '$currentDate': { 'lastUpdated': { '$type': 'timestamp' } } }
```
Also, for timestamp an alias operator is defined in `mongo-dot-notation`:
```javascript
var $ = require('mongo-dot-notation');
var $ = require('mongo-dot-notation')
$.flatten({
lastUpdate: $.$timestamp()
})
// { '$currentDate': { 'lastUpdated': { '$type': 'timestamp' } } }
```
// $.$inc(value) increment value, defaults to 1
// $.$mul(value) multiply factor, defaults to 1
// $.$rename(name) renames a field with a given name
// $.$setOnInsert(value) sets the value only when inserted
// $.$set(value) sets the value. This is an implicit operator, meaning:
// {a: 1} and {a: $set(1)} are equivalent
// $.$unset() removes the field
// $.$min(value) only updates the field if the specified value is less than the existing field value
// $.$max(value) only updates the field if the specified value is greater than the existing field value
// $.$currentDate() sets the value of a field to current date as a Date
// $.$currentDate(type) where type=<date|timestamp> sets the value of a field to current date or timestamp
// $.$timestamp() sets the value of a field to current date as a Timestamp
### Array update operators
#### `.$ (update)`
See mongo [**$ (update)**](https://docs.mongodb.com/manual/reference/operator/update/positional/).
The positional `$` operator identifies an element in an array to update without explicitly specifying the position of the element in the array.
```javascript
var $ = require('mongo-dot-notation')
db.students.update(
{ _id: 1, grades: 80 }, // match all elements from grades array where value equals to 80
$.flatten({
grades: $.$().$set(82) // for matched elements, update value to 82
})
)
// { $set: { "grades.$" : 82 } }
```
> Copyright © 2015-2017 Dumitru Deveatii, released under the MIT license
In order to update the matched document's field:
```javascript
var $ = require('mongo-dot-notation')
db.students.update(
{ _id: 1, 'grades.grade': 80 },
$.flatten({
grades: $.$('std').$set(1.5)
})
)
// { $set: { "grades.$.std" : 1.5 } }
```
The positional `$` operator is chainable with all mongo supported update fields.
```javascript
var $ = require('mongo-dot-notation')
db.students.update(
{ _id: 1, grades: 80 },
$.flatten({
grades: $.$().$mul(0.1) //multiplies matched array element by 0.1
})
)
// { $mul: { "grades.$" : 0.1 } }
```
Can also be used to update an array element by a given index:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
grades: $.$(0).$set(100)
})
// { $set: { "grades.0" : 0.1 } }
```
Same, when updating the element's field:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
months: $.$('5.avgTemp').$set(25.7)
})
// { $set: { "months.5.avgTemp" : 25.7 } }
```
#### `.$addToSet`
See mongo [**$addToSet**](https://docs.mongodb.com/manual/reference/operator/update/addToSet).
The `$addToSet` operator adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$addToSet(5)
})
// { '$addToSet': { 'values': 5 } }
```
To add each value from a given array:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$addToSet([7, 1, 4]).$each()
})
// { '$addToSet': { 'values': { '$each': [7, 1, 4] } } }
```
#### `.$pop`
See mongo [**$pop**](https://docs.mongodb.com/manual/reference/operator/update/pop).
The `$pop` operator removes the first or last element of an array. Pass $pop a value of -1 to remove the first element of an array and 1 to remove the last element in an array.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pop() // removes by default last element
})
// { '$pop': { 'values': 1 } }
```
To remove first element from the array:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pop(-1)
})
// { '$pop': { 'values': -1 } }
```
There are chainable `.first()` and `.last()` methods defined:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
indexes: $.$pop().first(),
scores: $.$pop().last(),
})
// { '$pop': { 'indexes': -1, scores: 1 } }
```
#### `.$pullAll`
See mongo [**$pullAll**](https://docs.mongodb.com/manual/reference/operator/update/pullAll/).
The `$pullAll` operator removes all instances of the specified values from an existing array.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pullAll([0, 1])
})
// { '$pullAll': { 'values': [0, 1] } }
```
#### `.$pull`
See mongo [**$pull**](https://docs.mongodb.com/manual/reference/operator/update/pull/).
The `$pull` operator removes from an existing array all instances of a value or values that match a specified condition.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pull(7)
})
// { '$pull': { 'values': 7 } }
```
If an array is provided, implicitly applies `$in` operator:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pull([0, 1])
})
// { '$pull': { 'values': { '$in': [0, 1] } } }
```
See mongo documentation for [conditions](https://docs.mongodb.com/manual/reference/operator/update/pull/#remove-all-items-that-match-a-specified-pull-condition).
#### `.$pushAll`
See mongo [**$pushAll**](https://docs.mongodb.com/manual/reference/operator/update/pushAll/).
The `$pushAll` operator appends the specified values to an array. (*Note that this operator is deprecated since mongo 2.4.*)
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
values: $.$pushAll([1, 2, 3])
})
// { '$pushAll': { 'values': [1, 2, 3] } }
```
#### `.$push`
See mongo [**$push**](https://docs.mongodb.com/manual/reference/operator/update/push/).
The `$push` operator appends a specified value to an array. Can also be used to slice and sort the array.
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
grades: $.$push({ grade: 'A' })
})
// { '$push': { 'grades': { grade: 'A' } } }
```
To push several values, chain with `.$each()`
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
grades: $.$push([{ grade: 'A' }, { grade: 'B' }]).$each()
})
// {
// '$push': {
// 'grades': {
// '$each': [{ grade: 'A' }, { grade: 'B' }]
// }
// }
// }
```
To push values at a specific position use `.$position()` (*requires the use of .$each(). Supported in mongo >= 2.6*)
```javascript
var $ = require('mongo-dot-notation')
// insert as a first element in the array
$.flatten({
grades: $.$push({ grade: 'A' }).$each().$position(0)
})
// {
// '$push': {
// 'grades': {
// '$each': [{ grade: 'A' }],
// '$position': 0
// }
// }
// }
```
To slice the array, use `.slice()` (*requires the use of .$each(). Supported in mongo >= 2.6*)
```javascript
var $ = require('mongo-dot-notation')
// insert the element and limit to last 10 values
$.flatten({
grades: $.$push({ grade: 'A' }).$each().$slice(-10)
})
// {
// '$push': {
// 'grades': {
// '$each': [{ grade: 'A' }],
// '$slice': -10
// }
// }
// }
```
To sort the array, use `.sort()` (*requires the use of .$each(). Supported in mongo >= 2.4*)
```javascript
var $ = require('mongo-dot-notation')
// insert the element and sorts descending by grade
$.flatten({
grades: $.$push({ grade: 'A' }).$each().$sort({ grade: -1})
})
// {
// '$push': {
// 'grades': {
// '$each': [{ grade: 'A' }],
// '$sort': { grade: -1}
// }
// }
// }
```
Multiple instructions can be chained:
```javascript
var $ = require('mongo-dot-notation')
// insert the element, sorts descending by grade
// and slices only first 10 values
$.flatten({
grades: $.$push({ grade: 'A' }).$each().$sort({ grade: -1}).$slice(10)
})
// {
// '$push': {
// 'grades': {
// '$each': [{ grade: 'A' }],
// '$sort': { grade: -1},
// '$slice': 10
// }
// }
// }
```
In case the array needs only to be sorted and/or sliced, `mongo-dot-notation` defines aliases:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
grades: $.$sort({ grade: 1 }), // sames as $.push([]).$each().$sort({ grade: 1 })
scores: $.$slice(10), // sames as $.push([]).$each().$slice(1)
values: $.$sort().$slice(-5) // sames as $.push([]).$each().$sort().$slice(-5)
})
```
### Bitwise update operators
#### `.$bit`
See mongo [**$bit**](https://docs.mongodb.com/manual/reference/operator/update/bit/).
The `$bit` operator performs a bitwise update of a field. The operator supports bitwise AND, bitwise OR, and bitwise XOR (i.e. exclusive or) operations.
*Note XOR is supported in mongo >= 2.6*
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
owner: $.$bit().$and(7) // performs a bitwise AND
user: $.$bit().$or(1) // performans a bitwise OR
group: $.$bit().$xor(5) // performs a bitwise XOR
})
// {
// '$bit': {
// 'owner': { and: 7 },
// 'user': { or: 1 },
// 'group': { xor: 5 },
// }
// }
```
Following aliases are defined in `mongo-dot-notation`:
```javascript
var $ = require('mongo-dot-notation')
$.flatten({
owner: $.$and(7), // same as $.$bit().$and(7)
user: $.$or(1), // same as $.$bit().$or(1)
group: $.$xor(5), // same as $.$bit().$xor(5)
})
```
## License
[MIT](LICENSE)
Copyright © 2015-2017 Dumitru Deveatii

@@ -5,3 +5,3 @@ 'use strict';

var $ = require('../index');
var ObjectID = require('mongodb').ObjectID;
var mongo = require('mongodb');

@@ -35,7 +35,2 @@ describe('# Flatten tests', function(){

it('When is ObjectID returns the reference', function () {
var id = new ObjectID();
$.flatten(id).should.equal(id);
});
it('When is Array returns the array', function () {

@@ -52,4 +47,37 @@ var arr = [1, 2, 3];

describe('# MongoDB types', function(){
var supportedTypes = [
'Binary',
'Code',
'DBRef',
'Decimal128',
'Double',
'Int32',
'Long',
'MaxKey',
'MinKey',
'ObjectID',
'BSONRegExp',
'Symbol',
'Timestamp'
];
supportedTypes.forEach(function(mongoType){
describe(mongoType, function(){
it('Flatten directly', function(){
var id = new mongo[mongoType]();
$.flatten(id).should.equal(id);
});
it('Flatten as nested property', function(){
var data = {field: new mongo[mongoType]()};
$.flatten(data).should.have
.property('$set').that.have
.property('field').that.equals(data.field);
});
});
});
});
describe('# Simple objects', function () {
it('When has `a` string property sets the property', function () {

@@ -81,3 +109,30 @@ var obj = { a: 'test' };

describe('Empty values', function() {
describe('# Nested operators ($ positional operator)', function () {
it('When positional operator with $set', function () {
var obj = { points: $.$().$set(10) };
$.flatten(obj).should.deep.equal({ $set: { 'points.$': 10 } });
});
it('When positional operator with value', function () {
var obj = { points: $.$().value('test') };
$.flatten(obj).should.deep.equal({ $set: { 'points.$': 'test' } });
});
it('When positional operator with $inc', function () {
var obj = { points: $.$().$inc(-1) };
$.flatten(obj).should.deep.equal({ $inc: { 'points.$': -1 } });
});
it('When positional operator with field specified', function () {
var obj = { points: $.$('std').$set(0.5) };
$.flatten(obj).should.deep.equal({ $set: { 'points.$.std': 0.5 } });
});
it('When positional operator with field specified in nested object', function () {
var obj = {stats: { group: { points: $.$('std').$set(0.5) }}};
$.flatten(obj).should.deep.equal({ $set: { 'stats.group.points.$.std': 0.5 } });
});
});
describe('# Empty values', function() {

@@ -299,3 +354,3 @@ it('When property value is null sets to null', function () {

it('When has many inner properties with operators', function () {
var id = new ObjectID();
var id = new mongo.ObjectID();
var obj = {

@@ -302,0 +357,0 @@ id: id,

'use strict';
var MongoClient = require('mongodb').MongoClient;
var MongoTimestamp = require('mongodb').Timestamp;
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var MongoTimestamp = mongodb.Timestamp;
var MongoUrl = 'mongodb://localhost:27017/integration';

@@ -11,16 +12,21 @@

describe('# Integration tests', function() {
describe('Fields operators', function() {
var db;
var db;
before(function(done){
MongoClient.connect(MongoUrl)
.then(function(x){
db = x;
done();
});
});
after(function(){ return db.close(); });
describe('# Fields operators', function() {
var collection;
var searchCriteria = { email: 'john.doe@test.com' };
var getUser = function(){ return collection.findOne(searchCriteria); }
before(function(){ collection = db.collection('users'); });
before(function(done){
MongoClient.connect(MongoUrl)
.then(function(x){
db = x;
collection = db.collection('users');
done();
});
});
beforeEach(function(){

@@ -42,7 +48,5 @@ return collection.insertOne({

after(function(){ return db.close(); });
it('Updates name', function() {
it('Update name', function() {
return collection.update(searchCriteria, $.flatten({ 'firstName': 'Jack' }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){

@@ -53,105 +57,294 @@ return expect(x).to.have.property('firstName').that.equals('Jack');

it('Updates name to null', function () {
it('Update name to null', function () {
return collection.update(searchCriteria, $.flatten({ 'firstName': null }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('firstName').that.is.null; });
});
it('updates address city', function () {
it('Update address city', function () {
return collection.update(searchCriteria, $.flatten({ 'address': { 'city': 'Boston' } }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x.address).to.have.property('city').that.equals('Boston'); });
});
it('adds new address property: number', function () {
it('Add new `number` property to address', function () {
return collection.update(searchCriteria, $.flatten({ 'address': { 'number': 9 } }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ expect(x.address).to.have.property('number').that.equals(9); });
});
it('increments age by default with one', function () {
it('Increment age with default value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$inc() }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(31); });
});
it('increments age by 5', function () {
it('Increment age with 5', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$inc(5) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(35); });
});
it('multiply age by default with one', function () {
it('Multiply age with default value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$mul() }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ expect(x).to.have.property('age').that.equals(30); });
});
it('multiply age by two', function () {
it('Multiply age by two', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$mul(2) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(60); });
});
it('rename firstName to first_name', function () {
it('Rename firstName to first_name', function () {
return collection.update(searchCriteria, $.flatten({ firstName: $.$rename('first_name') }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('first_name').that.equals('John'); });
});
it('unset lastName', function () {
it('Unset lastName', function () {
return collection.update(searchCriteria, $.flatten({ lastName: $.$unset() }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.not.have.property('lastName'); });
});
it('min when less then', function () {
it('Update age to min when less than current value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$min(27) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(27); });
});
it('min when greater then', function () {
it('Update age to min when greater than current value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$min(47) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(30); });
});
it('max when less then', function () {
it('Update age to max when less than current value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$max(27) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(30); });
});
it('max when greater then', function () {
it('Update age to max when greater than current value', function () {
return collection.update(searchCriteria, $.flatten({ age: $.$max(47) }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('age').that.equals(47); });
});
it('sets current date', function () {
it('Set `updatedOn` to current date', function () {
return collection.update(searchCriteria, $.flatten({ updatedOn: $.$currentDate() }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('updatedOn').that.respondTo('getTime'); });
});
it('sets current timestamp', function () {
it('Set `time` to current timestamp', function () {
return collection.update(searchCriteria, $.flatten({ time: $.$timestamp() }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.have.property('time').that.is.instanceOf(MongoTimestamp); });
});
it('setOnInsert when updated results in no changes', function () {
it('Update `pass` with SetOnInsert', function () {
return collection.update(searchCriteria, $.flatten({ pass: $.$setOnInsert('change-me-next-time') }))
.then(function(){ return collection.findOne(searchCriteria); })
.then(getUser)
.then(function(x){ return expect(x).to.not.have.property('pass'); });
});
it('setOnInsert when inserted results in no changes', function () {
it('Insert `pass` with SetOnInsert', function () {
var criteria = {email: 'test@test.com'};
return collection.update(criteria, $.flatten({ pass: $.$setOnInsert('change-me-next-time') }), {upsert: true})
var value = 'change-me-next-time';
return collection.update(criteria, $.flatten({ pass: $.$setOnInsert(value) }), {upsert: true})
.then(function(){ return collection.findOne(criteria); })
.then(function(x){ return expect(x).to.have.property('pass').that.equals('change-me-next-time'); });
.then(function(x){ return expect(x).to.have.property('pass').that.equals(value); });
});
});
describe('# Array operators', function(){
//{ _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] }
var collection;
var searchCriteria = { _id: 1 };
var getUser = function(){ return collection.findOne(searchCriteria); }
before(function(){ collection = db.collection('users'); });
beforeEach(function(){ return collection.insertOne({ _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] }); });
afterEach(function(){ return collection.remove(); });
it('Increment value position found', function(){
return collection.update({ _id: 1, scores: {'$lt': 2} }, $.flatten({ scores: $.$().$inc(10) }))
.then(getUser)
.then(function(x){ return x.scores.should.include(10, 2, 5, 5, 11, 10).and.have.lengthOf(6); });
});
it('Unset value position found', function(){
return collection.update({ _id: 1, scores: {'$eq': 0} }, $.flatten({ scores: $.$().$unset() }))
.then(getUser)
.then(function(x){ return x.scores.should.include(null, 2, 5, 5, 1, null).and.have.lengthOf(6); });
});
it('Set field value position found', function(){
return collection.remove()
.then(function(){
collection.insertOne({
_id: 1,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
});
})
.then(function(){ return collection.update({_id: 1, 'grades.grade': 85 }, $.flatten({ grades: $.$('std').$set(6) })); })
.then(function(){ return collection.findOne({_id: 1, 'grades.grade': 85 }); })
.then(function(x){
return x.grades.should.deep.equal([
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 6 },
{ grade: 90, mean: 85, std: 3 }
]);
});
});
it('Add new element to set', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$addToSet(9) }))
.then(getUser)
.then(function(x){ return x.scores.should.include(9).and.have.lengthOf(7); });
});
it('Add existing element to set', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$addToSet(2) }))
.then(getUser)
.then(function(x){ return x.scores.should.include(2).and.have.lengthOf(6); });
});
it('Add array elements each', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$addToSet([2, 9]).$each() }))
.then(getUser)
.then(function(x){ return x.scores.should.include(9).and.have.lengthOf(7); });
});
it('Pop first element', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pop().first() }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([2, 5, 5, 1, 0]).and.have.lengthOf(5); });
});
it('Pop last element', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pop().last() }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 2, 5, 5, 1]).and.have.lengthOf(5); });
});
it('Pull all values of 5', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pullAll(5) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 2, 1, 0]).and.have.lengthOf(4); });
});
it('Pull all existing values', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pullAll([ 0, 2, 5, 5, 1, 0 ]) }))
.then(getUser)
.then(function(x){ return x.scores.should.have.lengthOf(0); });
});
it('Pull value 5', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pull(5) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 2, 1, 0]).and.have.lengthOf(4); });
});
it('Pull values gte 2', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pull({$gte: 2}) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 1, 0]).and.have.lengthOf(3); });
});
it('Pull an array of values', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pull([0, 1]) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([2, 5, 5]).and.have.lengthOf(3); });
});
it('Push all values [2, 3]', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$pushAll([2, 3]) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 2, 5, 5, 1, 0, 2, 3]).and.have.lengthOf(8); });
});
it('Push 9', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push(9) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 2, 5, 5, 1, 0, 9]).and.have.lengthOf(7); });
});
it('Push 9 at 0-position', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push(9).$each().$position(0) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([9, 0, 2, 5, 5, 1, 0]).and.have.lengthOf(7); });
});
it('Push 9 and slice last 3 values', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push(9).$each().$slice(-3) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([1, 0, 9]).and.have.lengthOf(3); });
});
it('Push 9 and sort ASC', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push(9).$each().$sort() }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 0, 1, 2, 5, 5, 9]).and.have.lengthOf(7); });
});
it('Push 9 and sort DESC', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push(9).$each().$sort(-1) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([9, 5, 5, 2, 1, 0, 0]).and.have.lengthOf(7); });
});
it('Push [9, 99], sort ASC and slice last 3', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push([9, 99]).$each().$sort().$slice(-3) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([5, 9, 99]).and.have.lengthOf(3); });
});
it('Push [9, 99], sort ASC and slice first 3', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push([9, 99]).$each().$sort().$slice(3) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 0, 1]).and.have.lengthOf(3); });
});
it('Push [9, 99], at position 1 and slice first 3', function () {
return collection.update(searchCriteria, $.flatten({ scores: $.$push([9, 99]).$each().$position(1).$slice(3) }))
.then(getUser)
.then(function(x){ return x.scores.should.deep.equal([0, 9, 99]).and.have.lengthOf(3); });
});
});
describe('# Bitwise operators', function(){
var collection;
var searchCriteria = { map: 'NY' };
var getPoint = function(){ return collection.findOne(searchCriteria); }
before(function(){ collection = db.collection('users'); });
beforeEach(function(){ return collection.insertOne({ map: 'NY', value: 11 }); });
afterEach(function(){ return collection.remove(); });
it('Perform bitwise AND operation 11 & 7 = 1011 & 0111 = 0011 = 3', function () {
return collection.update(searchCriteria, $.flatten({ value: $.$and(7) }))
.then(getPoint)
.then(function(x){ return x.value.should.equal(3); });
});
it('Perform bitwise OR operation 11 | 7 = 1011 & 0111 = 1111 = 15', function () {
return collection.update(searchCriteria, $.flatten({ value: $.$or(7) }))
.then(getPoint)
.then(function(x){ return x.value.should.equal(15); });
});
it('Perform bitwise XOR operation 11 | 7 = 1011 & 0111 = 1100 = 12', function () {
return collection.update(searchCriteria, $.flatten({ value: $.$xor(7) }))
.then(getPoint)
.then(function(x){ return x.value.should.equal(12); });
});
});
});
'use strict';
var should = require('chai').should();
var expect = require('chai').expect;
var $ = require('../index');
var Operator = require('../lib/operator');
describe('# Update operators', function () {
describe('$inc', function () {
it('When argument is undefined defaults to 1', function () {
$.$inc().value().should.equal(1);
describe('# Internals', function(){
describe('# Operator', function(){
it('Defines isOperator methos', function(){
Operator.should.itself.respondTo('isOperator');
});
it('When argument is set uses its value', function () {
var value = 123;
$.$inc(value).value().should.equal(value);
it('When null name throws', function(){
expect(function(){ new Operator(); }).to.throw();
});
});
describe('$mul', function () {
it('When argument is undefined defaults to 1', function () {
$.$mul().value().should.equal(1);
it('Name is set', function(){
new Operator('inc').should.have.property('name').
that.equals('inc');
});
it('When argument is set uses its value', function () {
var value = 10;
$.$mul(value).value().should.equal(value);
it('When value not set defaults to undefined', function(){
expect(new Operator('test').value()).to.be.undefined;
});
});
describe('$rename', function(){
it('Has expected value', function () {
var value = 'test';
$.$rename(value).value().should.equal(value);
it('When value set to null returns null value', function(){
expect(new Operator('test').value(null).value()).to.be.null;
});
});
describe('$setOnInsert', function(){
it('Has expected value', function () {
var value = {x: 10, y: 20};
$.$setOnInsert(value).value().should.equal(value);
it('When value set returns same value', function(){
var val = {};
new Operator('test').value(val).value().should.equal(val);
});
});
describe('$set', function(){
it('Has expected value', function () {
var value = { x: 10, y: 20 };
$.$set(value).value().should.equal(value);
it('When value set chains self', function(){
var op = new Operator('test');
op.value({}).should.equal(op);
});
});
});
describe('$unset', function(){
it('Has empty string value', function () {
$.$unset().value().should.equal('');
describe('# Update operators', function () {
describe('# Field', function(){
describe('$inc', function () {
it('Is operator', function () {
$.isOperator($.$inc()).should.be.true;
});
it('Has $inc name', function () {
$.$inc().name.should.equal('$inc');
});
it('When argument is undefined defaults to 1', function () {
$.$inc().value().should.equal(1);
});
it('When argument is set uses its value', function () {
var value = 123;
$.$inc(value).value().should.equal(value);
});
});
});
describe('$min', function(){
it('Has expected value', function () {
var value = 10;
$.$min(value).value().should.equal(value);
describe('$mul', function () {
it('Is operator', function () {
$.isOperator($.$mul()).should.be.true;
});
it('Has $mul name', function () {
$.$mul().name.should.equal('$mul');
});
it('When argument is undefined defaults to 1', function () {
$.$mul().value().should.equal(1);
});
it('When argument is set uses its value', function () {
var value = 10;
$.$mul(value).value().should.equal(value);
});
});
});
describe('$max', function(){
it('Has expected value', function () {
var value = 10;
$.$max(value).value().should.equal(value);
describe('$rename', function(){
it('Is operator', function () {
$.isOperator($.$rename('field')).should.be.true;
});
it('Has $rename name', function () {
$.$rename('field').name.should.equal('$rename');
});
it('Has expected value', function () {
var value = 'test';
$.$rename(value).value().should.equal(value);
});
});
});
describe('$currentDate', function(){
it('When argument is undefined defaults to date type', function () {
$.$currentDate().value().should.be.deep.equal({ $type: 'date' });
describe('$setOnInsert', function(){
it('Is operator', function () {
$.isOperator($.$setOnInsert(1)).should.be.true;
});
it('Has $setOnInsert name', function () {
$.$setOnInsert(10).name.should.equal('$setOnInsert');
});
it('Has expected value', function () {
var value = {x: 10, y: 20};
$.$setOnInsert(value).value().should.equal(value);
});
});
it('When argument is set uses its value', function () {
$.$currentDate('timestamp').value()
.should.be.deep.equal({ $type: 'timestamp' });
describe('$set', function(){
it('Is operator', function () {
$.isOperator($.$set(1)).should.be.true;
});
it('Has $set name', function () {
$.$set(10).name.should.equal('$set');
});
it('Has expected value', function () {
var value = { x: 10, y: 20 };
$.$set(value).value().should.equal(value);
});
});
describe('$unset', function(){
it('Is operator', function () {
$.isOperator($.$unset()).should.be.true;
});
it('Has $unset name', function () {
$.$unset().name.should.equal('$unset');
});
it('Has empty string value', function () {
$.$unset().value().should.equal('');
});
});
describe('$min', function(){
it('Is operator', function () {
$.isOperator($.$min(1)).should.be.true;
});
it('Has $min name', function () {
$.$min(1).name.should.equal('$min');
});
it('Has expected value', function () {
var value = 10;
$.$min(value).value().should.equal(value);
});
});
describe('$max', function(){
it('Is operator', function () {
$.isOperator($.$max(1)).should.be.true;
});
it('Has $max name', function () {
$.$max(1).name.should.equal('$max');
});
it('Has expected value', function () {
var value = 10;
$.$max(value).value().should.equal(value);
});
});
describe('$currentDate', function(){
it('Is operator', function () {
$.isOperator($.$currentDate()).should.be.true;
});
it('Has $currentDate name', function () {
$.$currentDate().name.should.equal('$currentDate');
});
it('When argument is undefined defaults to date type', function () {
$.$currentDate().value().should.be.deep.equal({ $type: 'date' });
});
it('When argument is set uses its value', function () {
$.$currentDate('timestamp').value()
.should.be.deep.equal({ $type: 'timestamp' });
});
});
describe('$timestamp *', function(){
it('Is operator', function () {
$.isOperator($.$timestamp()).should.be.true;
});
it('Has $currentDate name', function () {
$.$timestamp().name.should.equal('$currentDate');
});
it('Has timestamp type value', function () {
$.$timestamp().value().should.be.deep.equal({ $type: 'timestamp' });
});
});
});
describe('# Array', function(){
describe('$', function(){
it('Is operator', function () {
$.isOperator($.$()).should.be.true;
});
it('Has $ name when no field specified', function(){
$.$().name.should.equal('$');
});
it('Appends field to name when field specified', function(){
$.$('std').name.should.equal('$.std');
});
it('Appends index when number specified', function(){
$.$(3).name.should.equal('3');
});
describe('$timestamp', function(){
it('Has timestamp type value', function () {
$.$timestamp().value().should.be.deep.equal({ $type: 'timestamp' });
it('Appends index when string number specified', function(){
$.$('3').name.should.equal('3');
});
it('Appends index with field when mathes number', function(){
$.$('3.std').name.should.equal('3.std');
});
it('Appends index with field when mathes 0', function(){
$.$('0.std').name.should.equal('0.std');
});
it('Value throws when not set', function(){
expect(function(){ $.$().value(); }).to.throw();
});
it('Value throws when not supported operator is set', function(){
expect(function(){ $.$().value($.$setOnInsert(10)); }).to.throw(/setOnInsert/);
});
it('When value set defaults to $set', function(){
$.$().value(101).value().value().should.equal(101);
});
it('When value set with $set with null', function(){
expect($.$().value($.$set(null)).value().value()).to.be.null;
});
it('When value set to null', function(){
var operator = $.$unset();
expect($.$().value($.$set(null)).value().value()).to.be.null;
});
it('When value set with operator returns operator', function(){
var operator = $.$unset();
$.$().value(operator).value().should.equal(operator);
});
it('When chained operator', function(){
$.$().$inc(10).value().should.have.property('name').that.equals('$inc');
});
it('Is chainable with $inc', function(){
$.$().should.respondTo('$inc');
});
it('Is chainable with $mul', function(){
$.$().should.respondTo('$mul');
});
it('Is chainable with $set', function(){
$.$().should.respondTo('$set');
});
it('Is chainable with $unset', function(){
$.$().should.respondTo('$unset');
});
it('Is chainable with $min', function(){
$.$().should.respondTo('$min');
});
it('Is chainable with $max', function(){
$.$().should.respondTo('$max');
});
it('Is chainable with $currentDate', function(){
$.$().should.respondTo('$currentDate');
});
it('Is chainable with $timestamp', function(){
$.$().should.respondTo('$timestamp');
});
});
describe('$addToSet', function(){
it('Is operator', function () {
$.isOperator($.$addToSet(1)).should.be.true;
});
it('Has $addToSet name', function () {
$.$addToSet(1).name.should.equal('$addToSet');
});
it('When is null value', function () {
expect($.$addToSet(null).value()).to.be.null;
});
it('When is scalar value', function () {
var value = 10;
$.$addToSet(value).value().should.equal(value);
});
it('When is null value with each', function () {
$.$addToSet(null).$each().value().should.deep.equal({ '$each': [null] });
});
it('When is array value', function () {
var value = [1, 2, 3];
$.$addToSet(value).value().should.equal(value);
});
it('When is scalar value with each', function () {
var value = 10;
$.$addToSet(value).$each().value().should.deep.equal({ '$each': [10] });
});
it('When is array value with each', function () {
var value = [1, 2, 3];
$.$addToSet(value).$each().value().should.deep.equal({ '$each': [1, 2, 3] });
});
});
describe('$pop', function(){
it('Is operator', function () {
$.isOperator($.$pop(1)).should.be.true;
});
it('Has $pop name', function () {
$.$pop(1).name.should.equal('$pop');
});
it('When direction not specified uses 1 by default', function(){
$.$pop().value().should.equal(1);
});
it('When direction is 1 uses 1', function(){
$.$pop(1).value().should.equal(1);
});
it('When direction is -1 uses -1', function(){
$.$pop(-1).value().should.equal(-1);
});
it('When chained with first uses -1', function(){
$.$pop().first().value().should.equal(-1);
});
it('When chained with last uses 1', function(){
$.$pop().last().value().should.equal(1);
});
});
describe('$pullAll', function(){
it('Is operator', function () {
$.isOperator($.$pullAll(1)).should.be.true;
});
it('Has $pullAll name', function () {
$.$pullAll(1).name.should.equal('$pullAll');
});
it('When null value specified returns array of null element', function(){
$.$pullAll(null).value().should.deep.equal([null]);
});
it('When empty array specified returns empty array', function(){
$.$pullAll([]).value().should.deep.equal([]);
});
it('When value specified returns array of value element', function(){
var value = 'Test';
$.$pullAll(value).value().should.deep.equal([value]);
});
it('When array specified returns array', function(){
var value = [1, 2, 3];
$.$pullAll(value).value().should.deep.equal(value);
})
});
describe('$pull', function(){
it('Is operator', function () {
$.isOperator($.$pull(1)).should.be.true;
});
it('Has $pull name', function () {
$.$pull(1).name.should.equal('$pull');
});
it('When null value specified returns null', function(){
expect($.$pull(null).value()).to.equal(null);
});
it('When scalar value specified returns value', function(){
var value = 100;
$.$pull(value).value().should.to.equal(value);
});
it('When object value specified returns value', function(){
var value = { score: 8, item: "B" };
$.$pull(value).value().should.to.deep.equal(value);
});
it('When array value specified applies $in operator', function(){
var value = ['A', 'B', 'C'];
$.$pull(value).value().should.to.deep.equal({ '$in': value });
});
});
describe('$pushAll', function(){
it('Is operator', function () {
$.isOperator($.$pushAll(1)).should.be.true;
});
it('Has $pushAll name', function () {
$.$pushAll(1).name.should.equal('$pushAll');
});
it('When null value specified returns null', function(){
expect($.$pushAll(null).value()).to.deep.equal([null]);
});
it('When scalar value specified returns array of value', function(){
var value = 100;
$.$pushAll(value).value().should.deep.equal([value]);
});
it('When object value specified returns array of value', function(){
var value = { score: 8, item: 'B' };
$.$pushAll(value).value().should.deep.equal([value]);
});
it('When array value specified returns array', function(){
var value = ['A', 'B', 'C'];
$.$pushAll(value).value().should.deep.equal(value);
});
});
describe('$push', function(){
it('Is operator', function () {
$.isOperator($.$push(1)).should.be.true;
});
it('Has $push name', function(){
$.$push().name.should.equal('$push');
});
it('When null value specified returns null', function(){
expect($.$push(null).value()).to.equal(null);
});
it('When undefined value specified returns undefined', function(){
expect($.$push().value()).to.equal(undefined);
});
it('When scalar value specified returns value', function(){
var value = 9;
$.$push(value).value().should.equal(value);
});
it('When object value specified returns value', function(){
var value = { data: 'test'};
$.$push(value).value().should.deep.equal(value);
});
it('When array value specified returns array', function(){
var value = [1, 2, 3];
$.$push(value).value().should.deep.equal(value);
});
it('When no value specified with $each', function(){
$.$push().$each().value().should.deep.equal({ '$each': []});
});
it('When scalar value specified with $each', function(){
var value = 100;
$.$push(value).$each().value().should.deep.equal({ '$each': [value]});
});
it('When array value specified with $each', function(){
var value = [1, 2, 3];
$.$push(value).$each().value().should.deep.equal({ '$each': value});
});
it('When using $slice without $each throws', function(){
expect(function(){ $.$push(10).$slice(1); }).to.throw(/\$slice/);
});
it('When using $slice with empty value is ignored', function(){
$.$push(10).$each().$slice().value()
.should.deep.equal({'$each': [10]});
});
it('When using $slice sets value', function(){
$.$push(10).$each().$slice(-3).value()
.should.deep.equal({'$each': [10], '$slice': -3});
});
it('When using $sort without $each throws', function(){
expect(function(){ $.$push(10).$sort(1); }).to.throw(/\$sort/);
});
it('When using $sort with empty value uses 1 by default', function(){
$.$push(10).$each().$sort().value()
.should.deep.equal({'$each': [10], '$sort': 1});
});
it('When using $sort sets value', function(){
$.$push(10).$each().$sort({ val: 1 }).value()
.should.deep.equal({'$each': [10], '$sort': { val: 1}});
});
it('When using $position without $each throws', function(){
expect(function(){ $.$push(10).$position(1); }).to.throw(/\$position/);
});
it('When using $position with empty value is ignored', function(){
$.$push(10).$each().$position().value()
.should.deep.equal({'$each': [10]});
});
it('When using $position sets value', function(){
$.$push(10).$each().$position(0).value()
.should.deep.equal({'$each': [10], '$position': 0});
});
it('When using $each, $slice, $sort and $position', function(){
$.$push([{score: 9}, {score: 10}, {score: 7}])
.$each()
.$position(0)
.$sort({score: -1})
.$slice(3)
.value()
.should.deep.equal({
'$each': [{score: 9}, {score: 10}, {score: 7}],
'$sort': {score: -1},
'$slice': 3,
'$position': 0
})
});
});
describe('$slice *', function(){
it('Is operator', function () {
$.isOperator($.$slice(1)).should.be.true;
});
it('Has $push name', function(){
$.$slice(1).name.should.equal('$push');
});
it('Is same as $push of empty array', function(){
$.$slice(1).value().should.deep.equal({ '$each': [], '$slice': 1 });
});
});
describe('$sort *', function(){
it('Is operator', function () {
$.isOperator($.$sort(1)).should.be.true;
});
it('Has $push name', function(){
$.$sort(1).name.should.equal('$push');
});
it('Is same as $push of empty array', function(){
$.$sort(1).value().should.deep.equal({ '$each': [], '$sort': 1 });
});
});
});
describe('# Bitwise', function(){
describe('$bit', function(){
it('Is operator', function () {
$.isOperator($.$bit()).should.be.true;
});
it('Has $bit name', function(){
$.$bit().name.should.equal('$bit');
});
it('Is chainable with $and', function(){
$.$bit().should.respondTo('$and');
});
it('When chained with $and sets value', function(){
$.$bit().$and(1).value().should.deep.equal({ 'and': 1 });
});
it('Is chainable with $or', function(){
$.$bit().should.respondTo('$or');
});
it('When chained with $or sets value', function(){
$.$bit().$or(1).value().should.deep.equal({ 'or': 1 });
});
it('Is chainable with $xor', function(){
$.$bit().should.respondTo('$xor');
});
it('When chained with $or sets value', function(){
$.$bit().$xor(1).value().should.deep.equal({ 'xor': 1 });
});
it('Value throws', function(){
expect(function(){ $.$bit().value(); }).to.throw();
});
});
describe('$and *', function(){
it('Is operator', function () {
$.isOperator($.$and(5)).should.be.true;
});
it('Has $bit name', function(){
$.$and(5).name.should.equal('$bit');
});
it('When value provided', function(){
$.$and(5).value().should.deep.equal({ 'and': 5 });
});
});
describe('$or *', function(){
it('Is operator', function () {
$.isOperator($.$or(5)).should.be.true;
});
it('Has $bit name', function(){
$.$or(5).name.should.equal('$bit');
});
it('When value provided', function(){
$.$or(5).value().should.deep.equal({ 'or': 5 });
});
});
describe('$xor *', function(){
it('Is operator', function () {
$.isOperator($.$xor(5)).should.be.true;
});
it('Has $bit name', function(){
$.$xor(5).name.should.equal('$bit');
});
it('When value provided', function(){
$.$xor(5).value().should.deep.equal({ 'xor': 5 });
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc