Relative time queries (#4289)

* Add relative time queries

* Encode successful result

* Add integration test

* Add more error cases

* Remove unnecessary new Date

* Error when time has both 'in' and 'ago'

* naturalTimeToDate -> relativeTimeToDate

* Add $relativeTime operator

* Throw error if $relativeTime is invalid

* Add integration test for invalid relative time

* Exclude $exists query

* Only run integration tests on MongoDB

* Add it_only_db test helper
bd2ea87c1d/CONTRIBUTING.md (L23)

* Handle where val might be null or undefined

* Add integration test for multiple results

* Lowercase text before processing

* Always past if not future

* Precompute seconds multiplication

* Add shorthand for interval
hr, hrs
min, mins
sec, secs

* Throw error if $relativeTime is used with $exists, $ne, and $eq

* Improve coverage for relativeTimeToDate

* Add test for erroring on floating point units

* Remove unnecessary dropDatabase function

* Unit test $ne, $exists, $eq

* Verify field type

* Fix unit test for $exists
Unnest query object
This commit is contained in:
marvelm
2017-10-26 16:23:27 -04:00
committed by Florent Vilmart
parent 1dd58b7527
commit 6f1fe89948
5 changed files with 330 additions and 4 deletions

View File

@@ -3105,7 +3105,80 @@ describe('Parse.Query testing', () => {
equal(result.has('testPointerField'), result.get('shouldBe'));
});
done();
}
).catch(done.fail);
}).catch(done.fail);
});
it_only_db('mongo')('should handle relative times correctly', function(done) {
const now = Date.now();
const obj1 = new Parse.Object('MyCustomObject', {
name: 'obj1',
ttl: new Date(now + 2 * 24 * 60 * 60 * 1000), // 2 days from now
});
const obj2 = new Parse.Object('MyCustomObject', {
name: 'obj2',
ttl: new Date(now - 2 * 24 * 60 * 60 * 1000), // 2 days ago
});
Parse.Object.saveAll([obj1, obj2])
.then(() => {
const q = new Parse.Query('MyCustomObject');
q.greaterThan('ttl', { $relativeTime: 'in 1 day' });
return q.find({ useMasterKey: true });
})
.then((results) => {
expect(results.length).toBe(1);
})
.then(() => {
const q = new Parse.Query('MyCustomObject');
q.greaterThan('ttl', { $relativeTime: '1 day ago' });
return q.find({ useMasterKey: true });
})
.then((results) => {
expect(results.length).toBe(1);
})
.then(() => {
const q = new Parse.Query('MyCustomObject');
q.lessThan('ttl', { $relativeTime: '5 days ago' });
return q.find({ useMasterKey: true });
})
.then((results) => {
expect(results.length).toBe(0);
})
.then(() => {
const q = new Parse.Query('MyCustomObject');
q.greaterThan('ttl', { $relativeTime: '3 days ago' });
return q.find({ useMasterKey: true });
})
.then((results) => {
expect(results.length).toBe(2);
})
.then(done, done.fail);
});
it_only_db('mongo')('should error on invalid relative time', function(done) {
const obj1 = new Parse.Object('MyCustomObject', {
name: 'obj1',
ttl: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000), // 2 days from now
});
const q = new Parse.Query('MyCustomObject');
q.greaterThan('ttl', { $relativeTime: '-12 bananas ago' });
obj1.save({ useMasterKey: true })
.then(() => q.find({ useMasterKey: true }))
.then(done.fail, done);
});
it_only_db('mongo')('should error when using $relativeTime on non-Date field', function(done) {
const obj1 = new Parse.Object('MyCustomObject', {
name: 'obj1',
nonDateField: 'abcd',
ttl: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000), // 2 days from now
});
const q = new Parse.Query('MyCustomObject');
q.greaterThan('nonDateField', { $relativeTime: '1 day ago' });
obj1.save({ useMasterKey: true })
.then(() => q.find({ useMasterKey: true }))
.then(done.fail, done);
});
});