Merge branch 'release/2.13.0' into production
This commit is contained in:
commit
dfd26e4c23
118
CHANGES.md
118
CHANGES.md
|
@ -1,4 +1,42 @@
|
|||
2014-12-09, Version 2.12.0
|
||||
2015-01-07, Version 2.13.0
|
||||
==========================
|
||||
|
||||
* added test for sorting undefined values (Christian Vette)
|
||||
|
||||
* Fix the floating number comparison (Raymond Feng)
|
||||
|
||||
* Fix bad CLA URL in CONTRIBUTING.md (Ryan Graham)
|
||||
|
||||
* replace deprecated function __defineGetter__ (bitmage)
|
||||
|
||||
* add a flag to callback of findOrCreate to indicate find or create (Clark Wang)
|
||||
|
||||
* fix sorting of undefined values with multiple columns (Christian Vette)
|
||||
|
||||
* code style (cvette)
|
||||
|
||||
* fix sorting with undefined in memory connector (cvette)
|
||||
|
||||
* Added support for inline parameters like: new GeoPoint(-34, 150) (Simo Moujami)
|
||||
|
||||
* fix default include in default scope fails findById (Clark Wang)
|
||||
|
||||
* Added test for toString() (Simo Moujami)
|
||||
|
||||
* Additional formatting (Simo Moujami)
|
||||
|
||||
* Fixed constructor parameters and added bdd tests for constructor validation (Simo Moujami)
|
||||
|
||||
* Fixed indentation (Simo Moujami)
|
||||
|
||||
* Added mocha tests for GeoPoint (Simo Moujami)
|
||||
|
||||
* renamed intermediary variable (Simo Moujami)
|
||||
|
||||
* Fixed the haversine formula to calculate distance between 2 points properly (Simo Moujami)
|
||||
|
||||
|
||||
2014-12-08, Version 2.12.0
|
||||
==========================
|
||||
|
||||
* Relax the id comparison (Raymond Feng)
|
||||
|
@ -391,19 +429,16 @@
|
|||
|
||||
* Cleanup mixin tests (Fabien Franzen)
|
||||
|
||||
* Fix a name conflict in scope metadata (Raymond Feng)
|
||||
|
||||
|
||||
2014-08-08, Version 2.3.0
|
||||
=========================
|
||||
|
||||
|
||||
|
||||
2014-08-08, Version 2.3.1
|
||||
=========================
|
||||
|
||||
* Fix a name conflict in scope metadata (Raymond Feng)
|
||||
|
||||
|
||||
2014-08-08, Version 2.3.0
|
||||
=========================
|
||||
|
||||
* Fix the test case so that it works with other DBs (Raymond Feng)
|
||||
|
||||
* Bump version (Raymond Feng)
|
||||
|
@ -516,6 +551,8 @@
|
|||
|
||||
* Implemented embedsMany relation (Fabien Franzen)
|
||||
|
||||
* Fix a regression where undefined id should not match any record (Raymond Feng)
|
||||
|
||||
* Minor tweaks; pass-through properties/scope for hasAndBelongsToMany (Fabien Franzen)
|
||||
|
||||
* Implemented polymorphic hasMany through inverse (Fabien Franzen)
|
||||
|
@ -531,6 +568,11 @@
|
|||
* Implemented polymorphic hasMany (Fabien Franzen)
|
||||
|
||||
|
||||
2014-07-27, Version 2.1.0
|
||||
=========================
|
||||
|
||||
|
||||
|
||||
2014-07-27, Version 2.1.1
|
||||
=========================
|
||||
|
||||
|
@ -538,12 +580,6 @@
|
|||
|
||||
* Fix a regression where undefined id should not match any record (Raymond Feng)
|
||||
|
||||
|
||||
2014-07-27, Version 2.1.0
|
||||
=========================
|
||||
|
||||
* Bump version (Raymond Feng)
|
||||
|
||||
* datasource: support connectors without `getTypes` (Miroslav Bajtoš)
|
||||
|
||||
* relation: add `scope._target` for `hasOne` (Miroslav Bajtoš)
|
||||
|
@ -628,6 +664,10 @@
|
|||
|
||||
* Add missing inflection dep back (Raymond Feng)
|
||||
|
||||
|
||||
2014-07-15, Version 2.0.0-beta3
|
||||
===============================
|
||||
|
||||
* Bump version (Raymond Feng)
|
||||
|
||||
* 2.0.0-beta2 (Miroslav Bajtoš)
|
||||
|
@ -664,17 +704,12 @@
|
|||
2014-07-15, Version 1.7.0
|
||||
=========================
|
||||
|
||||
|
||||
|
||||
2014-07-15, Version 2.0.0-beta3
|
||||
===============================
|
||||
|
||||
* Bump version (Raymond Feng)
|
||||
|
||||
* Make sure related properties are defined for RDBMS (Raymond Feng)
|
||||
|
||||
* Test instance or id by the model type (Raymond Feng)
|
||||
|
||||
* Bump version (Raymond Feng)
|
||||
|
||||
* Allow before hooks to pass arguments to next() (Raymond Feng)
|
||||
|
||||
* Remoting methods for hasMany through (Raymond Feng)
|
||||
|
@ -699,36 +734,6 @@
|
|||
|
||||
* DAO.prototype.exists should return 'boolean' type. (Samuel Reed)
|
||||
|
||||
* 2.0.0-beta2 (Miroslav Bajtoš)
|
||||
|
||||
* validations: support non-V8 browsers (Miroslav Bajtoš)
|
||||
|
||||
* Remove remoting metadata (Raymond Feng)
|
||||
|
||||
* Fix the forEach closure (Raymond Feng)
|
||||
|
||||
* ModelBuilder: add `prototype.defineValueType` (Miroslav Bajtoš)
|
||||
|
||||
* Replace connector base with loopback-connector (Miroslav Bajtoš)
|
||||
|
||||
* Remove unsupported connectors (Miroslav Bajtoš)
|
||||
|
||||
* 2.0.0-beta1 (Ritchie Martori)
|
||||
|
||||
* Keep undefined/null values for the array type (Raymond Feng)
|
||||
|
||||
* Remove JSDocs for scopeMethods.add(acInst) and scopeMethods.remove(acInst) (crandmck)
|
||||
|
||||
* Copy info from api-model.md to JSDoc (crandmck)
|
||||
|
||||
* !fixup Remove additional remoting (Ritchie Martori)
|
||||
|
||||
* !fixup Require ._delegate for fn override (Ritchie Martori)
|
||||
|
||||
* Remove relation remoting (Ritchie Martori)
|
||||
|
||||
* Remove remoting metadata (Ritchie Martori)
|
||||
|
||||
|
||||
2014-07-03, Version 1.6.3
|
||||
=========================
|
||||
|
@ -1091,8 +1096,6 @@
|
|||
|
||||
* Simplify the test case (Raymond Feng)
|
||||
|
||||
* Revert the inflection version due to regression in camelize (Raymond Feng)
|
||||
|
||||
* Add unit test for datatype handling in updateAttributes. (arlaneenalra)
|
||||
|
||||
* Move new var into thunk. (arlaneenalra)
|
||||
|
@ -1100,11 +1103,6 @@
|
|||
* Use type converted data when writing back to database. (arlaneenalra)
|
||||
|
||||
|
||||
2014-02-11, Version 1.3.0
|
||||
=========================
|
||||
|
||||
|
||||
|
||||
2014-02-11, Version 1.3.1
|
||||
=========================
|
||||
|
||||
|
@ -1112,6 +1110,10 @@
|
|||
|
||||
* Revert the inflection version due to regression in camelize (Raymond Feng)
|
||||
|
||||
|
||||
2014-02-11, Version 1.3.0
|
||||
=========================
|
||||
|
||||
* Bump version and update deps (Raymond Feng)
|
||||
|
||||
* Add a test case (Raymond Feng)
|
||||
|
|
|
@ -14,7 +14,7 @@ Contributing to `loopback-datasource-juggler` is easy. In a few simple steps:
|
|||
* Adhere to code style outlined in the [Google C++ Style Guide][] and
|
||||
[Google Javascript Style Guide][].
|
||||
|
||||
* Sign the [Contributor License Agreement](https://cla.strongloop.com/strongloop/loopback-datasource-juggler)
|
||||
* Sign the [Contributor License Agreement](https://cla.strongloop.com/agreements/strongloop/loopback-datasource-juggler)
|
||||
|
||||
* Submit a pull request through Github.
|
||||
|
||||
|
|
8
index.js
8
index.js
|
@ -4,11 +4,11 @@ exports.ModelBaseClass = require('./lib/model.js');
|
|||
exports.GeoPoint = require('./lib/geo.js').GeoPoint;
|
||||
exports.ValidationError = require('./lib/validations.js').ValidationError;
|
||||
|
||||
exports.__defineGetter__('version', function () {
|
||||
return require('./package.json').version;
|
||||
Object.defineProperty(exports, 'version', {
|
||||
get: function() {return require('./package.json').version;}
|
||||
});
|
||||
|
||||
var commonTest = './test/common_test';
|
||||
exports.__defineGetter__('test', function () {
|
||||
return require(commonTest);
|
||||
Object.defineProperty(exports, 'test', {
|
||||
get: function() {return require(commonTest);}
|
||||
});
|
||||
|
|
|
@ -347,13 +347,19 @@ Memory.prototype.all = function all(model, filter, callback) {
|
|||
});
|
||||
|
||||
function sorting(a, b) {
|
||||
var undefinedA, undefinedB;
|
||||
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (a[this[i].key] > b[this[i].key]) {
|
||||
undefinedB = b[this[i].key] === undefined && a[this[i].key] !== undefined;
|
||||
undefinedA = a[this[i].key] === undefined && b[this[i].key] !== undefined;
|
||||
|
||||
if (undefinedB || a[this[i].key] > b[this[i].key]) {
|
||||
return 1 * this[i].reverse;
|
||||
} else if (a[this[i].key] < b[this[i].key]) {
|
||||
} else if (undefinedA || a[this[i].key] < b[this[i].key]) {
|
||||
return -1 * this[i].reverse;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,7 +58,6 @@ function byIdQuery(m, id) {
|
|||
var pk = idName(m);
|
||||
var query = { where: {} };
|
||||
query.where[pk] = id;
|
||||
m.applyScope(query);
|
||||
return query;
|
||||
}
|
||||
|
||||
|
@ -317,7 +316,7 @@ DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data
|
|||
* @param {Object} query Search conditions. See [find](#dataaccessobjectfindquery-callback) for query format.
|
||||
* For example: `{where: {test: 'me'}}`.
|
||||
* @param {Object} data Object to create.
|
||||
* @param {Function} cb Callback called with (err, instance)
|
||||
* @param {Function} cb Callback called with (err, instance, created)
|
||||
*/
|
||||
DataAccessObject.findOrCreate = function findOrCreate(query, data, callback) {
|
||||
if (query === undefined) {
|
||||
|
@ -335,8 +334,10 @@ DataAccessObject.findOrCreate = function findOrCreate(query, data, callback) {
|
|||
var t = this;
|
||||
this.findOne(query, function (err, record) {
|
||||
if (err) return callback(err);
|
||||
if (record) return callback(null, record);
|
||||
t.create(data, callback);
|
||||
if (record) return callback(null, record, false);
|
||||
t.create(data, function (err, record) {
|
||||
callback(err, record, record != null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
48
lib/geo.js
48
lib/geo.js
|
@ -111,7 +111,11 @@ exports.GeoPoint = GeoPoint;
|
|||
*
|
||||
* @options {Object} Options Object with two Number properties: lat and long.
|
||||
* @property {Number} lat The latitude point in degrees. Range: -90 to 90.
|
||||
* @property {Number} lng The longitude point in degrees. Range: -90 to 90.
|
||||
* @property {Number} lng The longitude point in degrees. Range: -180 to 180.
|
||||
*
|
||||
* @options {Array} Options Array with two Number entries: [lat,long].
|
||||
* @property {Number} lat The latitude point in degrees. Range: -90 to 90.
|
||||
* @property {Number} lng The longitude point in degrees. Range: -180 to 180.
|
||||
*/
|
||||
|
||||
function GeoPoint(data) {
|
||||
|
@ -119,14 +123,23 @@ function GeoPoint(data) {
|
|||
return new GeoPoint(data);
|
||||
}
|
||||
|
||||
if(arguments.length === 2) {
|
||||
data = {
|
||||
lat: arguments[0],
|
||||
lng: arguments[1]
|
||||
};
|
||||
}
|
||||
|
||||
assert(Array.isArray(data) || typeof data === 'object' || typeof data === 'string', 'must provide valid geo-coordinates array [lat, lng] or object or a "lat, lng" string');
|
||||
|
||||
if (typeof data === 'string') {
|
||||
data = data.split(/,\s*/);
|
||||
assert(data.length === 2, 'must provide a string "lng,lat" creating a GeoPoint with a string');
|
||||
assert(data.length === 2, 'must provide a string "lat,lng" creating a GeoPoint with a string');
|
||||
}
|
||||
if (Array.isArray(data)) {
|
||||
data = {
|
||||
lng: Number(data[0]),
|
||||
lat: Number(data[1])
|
||||
lat: Number(data[0]),
|
||||
lng: Number(data[1])
|
||||
};
|
||||
} else {
|
||||
data.lng = Number(data.lng);
|
||||
|
@ -177,7 +190,7 @@ GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
|
|||
var y2 = b.lng;
|
||||
|
||||
return geoDistance(x1, y1, x2, y2, options);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine the spherical distance to the given point.
|
||||
|
@ -202,26 +215,22 @@ GeoPoint.distanceBetween = function distanceBetween(a, b, options) {
|
|||
|
||||
GeoPoint.prototype.distanceTo = function (point, options) {
|
||||
return GeoPoint.distanceBetween(this, point, options);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple serialization.
|
||||
*/
|
||||
|
||||
GeoPoint.prototype.toString = function () {
|
||||
return this.lng + ',' + this.lat;
|
||||
}
|
||||
return this.lat + ',' + this.lng;
|
||||
};
|
||||
|
||||
/**
|
||||
* @property {Number} PI - Ratio of a circle's circumference to its diameter.
|
||||
* @property {Number} DEG2RAD - Factor to convert degrees to radians.
|
||||
* @property {Number} RAD2DEG - Factor to convert radians to degrees.
|
||||
* @property {Object} EARTH_RADIUS - Radius of the earth.
|
||||
*/
|
||||
|
||||
// ratio of a circle's circumference to its diameter
|
||||
var PI = 3.1415926535897932384626433832795;
|
||||
|
||||
// factor to convert degrees to radians
|
||||
var DEG2RAD = 0.01745329252;
|
||||
|
||||
|
@ -239,18 +248,23 @@ var EARTH_RADIUS = {
|
|||
};
|
||||
|
||||
function geoDistance(x1, y1, x2, y2, options) {
|
||||
|
||||
var type = (options && options.type) || 'miles';
|
||||
|
||||
// Convert to radians
|
||||
x1 = x1 * DEG2RAD;
|
||||
y1 = y1 * DEG2RAD;
|
||||
x2 = x2 * DEG2RAD;
|
||||
y2 = y2 * DEG2RAD;
|
||||
|
||||
var a = Math.pow(Math.sin(( y2 - y1 ) / 2.0), 2);
|
||||
var b = Math.pow(Math.sin(( x2 - x1 ) / 2.0), 2);
|
||||
var c = Math.sqrt(a + Math.cos(y2) * Math.cos(y1) * b);
|
||||
// use the haversine formula to calculate distance for any 2 points on a sphere.
|
||||
// ref http://en.wikipedia.org/wiki/Haversine_formula
|
||||
var haversine = function(a) {
|
||||
return Math.pow(Math.sin(a / 2.0), 2);
|
||||
};
|
||||
|
||||
var type = (options && options.type) || 'miles';
|
||||
var f = Math.sqrt(haversine(x2 - x1) + Math.cos(x2) * Math.cos(x1) * haversine(y2 - y1));
|
||||
|
||||
return 2 * Math.asin(c) * EARTH_RADIUS[type];
|
||||
return 2 * Math.asin(f) * EARTH_RADIUS[type];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "loopback-datasource-juggler",
|
||||
"version": "2.12.0",
|
||||
"version": "2.13.0",
|
||||
"description": "LoopBack DataSoure Juggler",
|
||||
"keywords": [
|
||||
"StrongLoop",
|
||||
|
|
|
@ -1122,12 +1122,14 @@ function testOrm(dataSource) {
|
|||
|
||||
it('should find or create', function (test) {
|
||||
var email = 'some email ' + Math.random();
|
||||
User.findOrCreate({where: {email: email}}, function (err, u) {
|
||||
User.findOrCreate({where: {email: email}}, function (err, u, created) {
|
||||
test.ok(u);
|
||||
test.ok(!u.age);
|
||||
User.findOrCreate({where: {email: email}}, {age: 21}, function (err, u2) {
|
||||
test.ok(created);
|
||||
User.findOrCreate({where: {email: email}}, {age: 21}, function (err, u2, created) {
|
||||
test.equals(u.id.toString(), u2.id.toString(), 'Same user ids');
|
||||
test.ok(!u2.age);
|
||||
test.ok(!created);
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
var should = require('./init.js');
|
||||
var async = require('async');
|
||||
|
||||
var db, Category, Product, Tool, Widget, Thing;
|
||||
var db, Category, Product, Tool, Widget, Thing, Person;
|
||||
|
||||
// This test requires a connector that can
|
||||
// handle a custom collection or table name
|
||||
|
@ -86,6 +86,10 @@ describe('default scope', function () {
|
|||
mongodb: { collection: 'Product' },
|
||||
memory: { collection: 'Product' }
|
||||
});
|
||||
|
||||
Person = db.define('Person', { name: String }, {
|
||||
scope: { include: 'things' }
|
||||
});
|
||||
|
||||
// inst is only valid for instance methods
|
||||
// like save, updateAttributes
|
||||
|
@ -115,6 +119,9 @@ describe('default scope', function () {
|
|||
Tool.belongsTo(Category);
|
||||
Widget.belongsTo(Category);
|
||||
Thing.belongsTo(Category);
|
||||
|
||||
Person.hasMany(Thing);
|
||||
Thing.belongsTo(Person);
|
||||
|
||||
db.automigrate(done);
|
||||
});
|
||||
|
@ -802,7 +809,33 @@ describe('default scope', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('with include option', function() {
|
||||
|
||||
before(function (done) {
|
||||
db.automigrate(done);
|
||||
});
|
||||
|
||||
before(function (done) {
|
||||
Person.create({ id: 1, name: 'Person A' }, function(err, person) {
|
||||
person.things.create({ name: 'Thing A' }, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should find a scoped instance with included relation - things', function(done) {
|
||||
Person.findById(1, function(err, person) {
|
||||
should.not.exist(err);
|
||||
should.exist(person);
|
||||
var things = person.things();
|
||||
should.exist(things);
|
||||
things.should.be.an.instanceOf(Array);
|
||||
things.should.have.length(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*global describe,it*/
|
||||
/*jshint expr:true */
|
||||
|
||||
require('should');
|
||||
|
||||
var GeoPoint = require('../lib/geo').GeoPoint;
|
||||
var DELTA = 0.0000001;
|
||||
|
||||
describe('GeoPoint', function () {
|
||||
|
||||
describe('constructor', function() {
|
||||
|
||||
it('should support a valid array', function () {
|
||||
var point = new GeoPoint([-34, 150]);
|
||||
|
||||
point.lat.should.equal(-34);
|
||||
point.lng.should.equal(150);
|
||||
});
|
||||
|
||||
it('should support a valid object', function () {
|
||||
var point = new GeoPoint({ lat: -34, lng: 150 });
|
||||
|
||||
point.lat.should.equal(-34);
|
||||
point.lng.should.equal(150);
|
||||
});
|
||||
|
||||
it('should support valid string geo coordinates', function () {
|
||||
var point = new GeoPoint('-34,150');
|
||||
|
||||
point.lat.should.equal(-34);
|
||||
point.lng.should.equal(150);
|
||||
});
|
||||
|
||||
it('should support coordinates as inline parameters', function () {
|
||||
var point = new GeoPoint(-34, 150);
|
||||
|
||||
point.lat.should.equal(-34);
|
||||
point.lng.should.equal(150);
|
||||
});
|
||||
|
||||
it('should reject invalid parameters', function () {
|
||||
/*jshint -W024 */
|
||||
var fn = function() {
|
||||
new GeoPoint('150,-34');
|
||||
};
|
||||
fn.should.throw();
|
||||
|
||||
fn = function() {
|
||||
new GeoPoint('invalid_string');
|
||||
};
|
||||
fn.should.throw();
|
||||
|
||||
fn = function() {
|
||||
new GeoPoint([150, -34]);
|
||||
};
|
||||
fn.should.throw();
|
||||
|
||||
fn = function() {
|
||||
new GeoPoint({
|
||||
lat: 150,
|
||||
lng: null
|
||||
});
|
||||
};
|
||||
fn.should.throw();
|
||||
|
||||
fn = function() {
|
||||
new GeoPoint(150, -34);
|
||||
};
|
||||
fn.should.throw();
|
||||
|
||||
fn = function() {
|
||||
new GeoPoint();
|
||||
};
|
||||
fn.should.throw();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('toString()', function() {
|
||||
|
||||
it('should return a string in the form "lat,lng"', function() {
|
||||
|
||||
var point = new GeoPoint({ lat: -34, lng: 150 });
|
||||
point.toString().should.equal('-34,150');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('distance calculation between two points', function () {
|
||||
|
||||
var here = new GeoPoint({ lat: 40.77492964101182, lng: -73.90950187151662 });
|
||||
var there = new GeoPoint({ lat: 40.7753227, lng: -73.909217 });
|
||||
|
||||
it('should return value in miles by default', function () {
|
||||
|
||||
var distance = GeoPoint.distanceBetween(here, there);
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(0.03097916611592679, DELTA);
|
||||
});
|
||||
|
||||
it('should return value using specified unit', function () {
|
||||
|
||||
/* Supported units:
|
||||
* - `radians`
|
||||
* - `kilometers`
|
||||
* - `meters`
|
||||
* - `miles`
|
||||
* - `feet`
|
||||
* - `degrees`
|
||||
*/
|
||||
|
||||
var distance = here.distanceTo(there, { type: 'radians'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(0.000007825491914348416, DELTA);
|
||||
|
||||
distance = here.distanceTo(there, { type: 'kilometers'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(0.04985613511367009, DELTA);
|
||||
|
||||
distance = here.distanceTo(there, { type: 'meters'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(49.856135113670085, DELTA);
|
||||
|
||||
distance = here.distanceTo(there, { type: 'miles'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(0.03097916611592679, DELTA);
|
||||
|
||||
distance = here.distanceTo(there, { type: 'feet'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(163.56999709209347, DELTA);
|
||||
|
||||
distance = here.distanceTo(there, { type: 'degrees'});
|
||||
distance.should.be.a.Number;
|
||||
distance.should.be.approximately(0.0004483676593058972, DELTA);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -183,7 +183,7 @@ describe('Memory connector', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('support order with multiple fields', function (done) {
|
||||
it('should support order with multiple fields', function (done) {
|
||||
User.find({order: 'vip ASC, seq DESC'}, function (err, posts) {
|
||||
should.not.exist(err);
|
||||
posts[0].seq.should.be.eql(4);
|
||||
|
@ -192,6 +192,17 @@ describe('Memory connector', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should sort undefined values to the end when ordered DESC', function (done) {
|
||||
User.find({order: 'vip ASC, order DESC'}, function (err, posts) {
|
||||
console.log(posts);
|
||||
should.not.exist(err);
|
||||
|
||||
posts[4].seq.should.be.eql(1);
|
||||
posts[5].seq.should.be.eql(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw if order has wrong direction', function (done) {
|
||||
User.find({order: 'seq ABC'}, function (err, posts) {
|
||||
should.exist(err);
|
||||
|
@ -200,11 +211,11 @@ describe('Memory connector', function () {
|
|||
});
|
||||
|
||||
it('should support neq operator for number', function (done) {
|
||||
User.find({where: {order: {neq: 6}}}, function (err, users) {
|
||||
User.find({where: {seq: {neq: 4}}}, function (err, users) {
|
||||
should.not.exist(err);
|
||||
users.length.should.be.equal(5);
|
||||
for (var i = 0; i < users.length; i++) {
|
||||
users[i].order.should.not.be.equal(6);
|
||||
users[i].seq.should.not.be.equal(4);
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
@ -242,7 +253,6 @@ describe('Memory connector', function () {
|
|||
email: 'john@b3atl3s.co.uk',
|
||||
role: 'lead',
|
||||
birthday: new Date('1980-12-08'),
|
||||
order: 2,
|
||||
vip: true
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue