sharedb-mongo 1.0.0-beta.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,469 @@
1
+ var async = require('async');
2
+ var sinon = require('sinon');
3
+ var chai = require('chai');
4
+ chai.use(require('sinon-chai'));
5
+ var expect = chai.expect;
6
+ var ShareDbMongo = require('..');
7
+ var mongodb = require('./../mongodb');
8
+ var Collection = mongodb.Collection;
9
+
10
+ var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test';
11
+ var BEFORE_EDIT = ShareDbMongo.MiddlewareActions.beforeOverwrite;
12
+ var BEFORE_CREATE = ShareDbMongo.MiddlewareActions.beforeCreate;
13
+ var BEFORE_SNAPSHOT_LOOKUP = ShareDbMongo.MiddlewareActions.beforeSnapshotLookup;
14
+
15
+ function create(callback) {
16
+ var db = new ShareDbMongo(mongoUrl);
17
+ db.getDbs(function(err, mongo) {
18
+ if (err) return callback(err);
19
+ mongo.dropDatabase(function(err) {
20
+ if (err) return callback(err);
21
+ callback(null, db, mongo);
22
+ });
23
+ });
24
+ }
25
+
26
+ describe('mongo db middleware', function() {
27
+ var sandbox = sinon.createSandbox();
28
+ var db;
29
+
30
+ beforeEach(function(done) {
31
+ sandbox.spy(Collection.prototype, 'find');
32
+ create(function(err, createdDb) {
33
+ if (err) return done(err);
34
+ db = createdDb;
35
+ done();
36
+ });
37
+ });
38
+
39
+ afterEach(function(done) {
40
+ sandbox.restore();
41
+ db.close(done);
42
+ });
43
+
44
+ describe('error handling', function() {
45
+ it('throws error when no action is given', function() {
46
+ function invalidAction() {
47
+ db.use(null, function(_request, next) {
48
+ next();
49
+ });
50
+ }
51
+ expect(invalidAction).to.throw();
52
+ });
53
+
54
+ it('throws error when no handler is given', function() {
55
+ function invalidAction() {
56
+ db.use('someAction');
57
+ }
58
+ expect(invalidAction).to.throw();
59
+ });
60
+
61
+ it('throws error on unrecognized action name', function() {
62
+ function invalidAction() {
63
+ db.use('someAction', function(_request, next) {
64
+ next();
65
+ });
66
+ }
67
+ expect(invalidAction).to.throw();
68
+ });
69
+ });
70
+
71
+ describe(BEFORE_EDIT, function() {
72
+ it('has the expected properties on the request object', function(done) {
73
+ db.use(BEFORE_EDIT, function(request, next) {
74
+ expect(request).to.have.all.keys([
75
+ 'action',
76
+ 'collectionName',
77
+ 'documentToWrite',
78
+ 'op',
79
+ 'options',
80
+ 'query'
81
+ ]);
82
+ expect(request.action).to.equal(BEFORE_EDIT);
83
+ expect(request.collectionName).to.equal('testcollection');
84
+ expect(request.documentToWrite.foo).to.equal('fuzz');
85
+ expect(request.op.op).to.exist;
86
+ expect(request.options.testOptions).to.equal('yes');
87
+ expect(request.query._id).to.equal('test1');
88
+ next();
89
+ done();
90
+ });
91
+
92
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
93
+ var editOp = {v: 2, op: [{p: ['foo'], oi: 'bar', oi: 'baz'}], m: {ts: Date.now()}};
94
+ var newSnapshot = {type: 'json0', id: 'test1', v: 2, data: {foo: 'fuzz'}};
95
+
96
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
97
+ if (err) return done(err);
98
+ db.commit('testcollection', snapshot.id, editOp, newSnapshot, {testOptions: 'yes'}, function(err) {
99
+ if (err) return done(err);
100
+ });
101
+ });
102
+ });
103
+
104
+ it('should augment query filter and write to the document when commit is called', function(done) {
105
+ // Augment the query. The original query looks up the document by id, wheras this middleware
106
+ // changes it to use the `foo` property. The end result still returns the same document. The next
107
+ // middleware ensures we attached it to the request.
108
+ // We can't truly change which document is returned from the query because MongoDB will not allow
109
+ // the immutable fields such as `_id` to be changed.
110
+ db.use(BEFORE_EDIT, function(request, next) {
111
+ request.query.foo = 'bar';
112
+ next();
113
+ });
114
+ // Attach this middleware to check that the original one is passing the context
115
+ // correctly. Commit will be called after this.
116
+ db.use(BEFORE_EDIT, function(request, next) {
117
+ expect(request.query).to.deep.equal({
118
+ _id: 'test1',
119
+ _v: 1,
120
+ foo: 'bar'
121
+ });
122
+ next();
123
+ });
124
+
125
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
126
+ var editOp = {v: 2, op: [{p: ['foo'], oi: 'bar', oi: 'baz'}], m: {ts: Date.now()}};
127
+ var newSnapshot = {type: 'json0', id: 'test1', v: 2, data: {foo: 'baz'}};
128
+
129
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
130
+ if (err) return done(err);
131
+ expectDocumentToContainFoo('bar', function() {
132
+ db.commit('testcollection', snapshot.id, editOp, newSnapshot, null, function(err) {
133
+ if (err) return done(err);
134
+ // Ensure the value is updated as expected
135
+ expectDocumentToContainFoo('baz', done);
136
+ });
137
+ });
138
+ });
139
+ });
140
+ });
141
+
142
+ it('should augment the written document when commit is called', function(done) {
143
+ // Change the written value of foo to be `fuzz`
144
+ db.use(BEFORE_EDIT, function(request, next) {
145
+ request.documentToWrite.foo = 'fuzz';
146
+ next();
147
+ });
148
+
149
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
150
+
151
+ // Issue a commit to change `bar` to `baz`
152
+ var editOp = {v: 2, op: [{p: ['foo'], oi: 'bar', oi: 'baz'}], m: {ts: Date.now()}};
153
+ var newSnapshot = {type: 'json0', id: 'test1', v: 2, data: {foo: 'baz'}};
154
+
155
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
156
+ if (err) return done(err);
157
+ expectDocumentToContainFoo('bar', function() {
158
+ db.commit('testcollection', snapshot.id, editOp, newSnapshot, null, function(err) {
159
+ if (err) return done(err);
160
+ // Ensure the value is updated as expected
161
+ expectDocumentToContainFoo('fuzz', done);
162
+ });
163
+ });
164
+ });
165
+ });
166
+
167
+ describe(BEFORE_CREATE, function() {
168
+ it('has the expected properties on the request object', function(done) {
169
+ db.use(BEFORE_CREATE, function(request, next) {
170
+ expect(request).to.have.all.keys([
171
+ 'action',
172
+ 'collectionName',
173
+ 'documentToWrite',
174
+ 'op',
175
+ 'options'
176
+ ]);
177
+ expect(request.action).to.equal(BEFORE_CREATE);
178
+ expect(request.collectionName).to.equal('testcollection');
179
+ expect(request.documentToWrite.foo).to.equal('bar');
180
+ expect(request.op).to.exist;
181
+ expect(request.options.testOptions).to.equal('baz');
182
+ next();
183
+ });
184
+
185
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
186
+
187
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, {testOptions: 'baz'}, done);
188
+ });
189
+
190
+ it('should augment the written document when commit is called', function(done) {
191
+ // Change the written value of foo to be `fuzz`
192
+ db.use(BEFORE_CREATE, function(request, next) {
193
+ request.documentToWrite.foo = 'fuzz';
194
+ next();
195
+ });
196
+
197
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
198
+
199
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
200
+ if (err) return done(err);
201
+ expectDocumentToContainFoo('fuzz', done);
202
+ });
203
+ });
204
+
205
+ it('returns without writing when there was a middleware error', function(done) {
206
+ db.use(BEFORE_CREATE, function(_, next) {
207
+ next(new Error('Oh no!'));
208
+ });
209
+
210
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
211
+
212
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
213
+ expectDocumentNotToExist(function() {
214
+ if (err) return done();
215
+ done('Expected an error, did not get one');
216
+ });
217
+ });
218
+ });
219
+ });
220
+
221
+ describe(BEFORE_SNAPSHOT_LOOKUP, function() {
222
+ it('has the expected properties on the request object before getting a single snapshot', function(done) {
223
+ db.use(BEFORE_SNAPSHOT_LOOKUP, function(request, next) {
224
+ expect(request).to.have.all.keys([
225
+ 'action',
226
+ 'collectionName',
227
+ 'options',
228
+ 'query'
229
+ ]);
230
+ expect(request.action).to.equal(BEFORE_SNAPSHOT_LOOKUP);
231
+ expect(request.collectionName).to.equal('testcollection');
232
+ expect(request.options.testOptions).to.equal('yes');
233
+ expect(request.query._id).to.equal('test1');
234
+ next();
235
+ done();
236
+ });
237
+
238
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
239
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
240
+ if (err) return done(err);
241
+ db.getSnapshot('testcollection', 'test1', null, {testOptions: 'yes'}, function(err, doc) {
242
+ if (err) return done(err);
243
+ expect(doc).to.exist;
244
+ });
245
+ });
246
+ });
247
+
248
+ it('passes triggeredBy = submitRequest when fields has $submit = true', function(done) {
249
+ var middlewareSpy = sinon.spy(function(request, next) {
250
+ expect(request).to.have.all.keys([
251
+ 'action',
252
+ 'collectionName',
253
+ 'options',
254
+ 'query',
255
+ 'triggeredBy'
256
+ ]);
257
+ expect(request.action).to.equal(BEFORE_SNAPSHOT_LOOKUP);
258
+ expect(request.collectionName).to.equal('testcollection');
259
+ expect(request.options.testOptions).to.equal('yes');
260
+ expect(request.triggeredBy).to.equal('submitRequest');
261
+ expect(request.query._id).to.equal('test1');
262
+ // test that when we set findOptions in the middleware, they get passed to the Mongo driver.
263
+ request.findOptions = {
264
+ maxTimeMS: 999
265
+ };
266
+ next();
267
+ });
268
+ db.use(BEFORE_SNAPSHOT_LOOKUP, middlewareSpy);
269
+
270
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
271
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
272
+ if (err) return done(err);
273
+ db.getSnapshot('testcollection', 'test1', {
274
+ $submit: true
275
+ }, {testOptions: 'yes'}, function(err, doc) {
276
+ if (err) return done(err);
277
+ expect(doc).to.exist;
278
+ expect(middlewareSpy).to.have.been.calledOnceWith(sinon.match.object, sinon.match.func);
279
+ expect(Collection.prototype.find).to.have.been.calledOnceWith({
280
+ _id: snapshot.id
281
+ }, {
282
+ maxTimeMS: 999
283
+ });
284
+ done();
285
+ });
286
+ });
287
+ });
288
+
289
+ it('has the expected properties on the request object before getting ops', function(done) {
290
+ var middlewareSpy = sinon.spy(function(request, next) {
291
+ expect(request).to.have.all.keys([
292
+ 'action',
293
+ 'collectionName',
294
+ 'options',
295
+ 'query'
296
+ ]);
297
+ expect(request.action).to.equal(BEFORE_SNAPSHOT_LOOKUP);
298
+ expect(request.collectionName).to.equal('testcollection');
299
+ expect(request.options.testOptions).to.equal('yes');
300
+ expect(request.query._id).to.deep.equal('test2');
301
+ next();
302
+ });
303
+ db.use(BEFORE_SNAPSHOT_LOOKUP, middlewareSpy);
304
+
305
+ var snapshot = {type: 'json0', id: 'test2', v: 1, data: {foo: 'bar'}};
306
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
307
+ if (err) return done(err);
308
+ db.getOps('testcollection', 'test2', 0, 1, {testOptions: 'yes'}, function(err) {
309
+ if (err) return done(err);
310
+ /*
311
+ Don't finalize the test in the middleware - since getOps will make queries *after* the middleware is fired.
312
+ If we call done() in the middleware, we'll close the db connection, and then getOps will call _getOps()
313
+ which will throw a "db connection closed" error.
314
+ */
315
+ expect(middlewareSpy).to.have.been.calledOnceWith(sinon.match.object, sinon.match.func);
316
+ done();
317
+ });
318
+ });
319
+ });
320
+
321
+ it('has the expected properties on the request object before getting ops bulk', function(done) {
322
+ var middlewareSpy = sinon.spy(function(request, next) {
323
+ expect(request).to.have.all.keys([
324
+ 'action',
325
+ 'collectionName',
326
+ 'options',
327
+ 'query'
328
+ ]);
329
+ expect(request.action).to.equal(BEFORE_SNAPSHOT_LOOKUP);
330
+ expect(request.collectionName).to.equal('testcollection');
331
+ expect(request.options.testOptions).to.equal('yes');
332
+ expect(request.query._id).to.deep.equal({$in: ['test2']});
333
+ next();
334
+ });
335
+ db.use(BEFORE_SNAPSHOT_LOOKUP, middlewareSpy);
336
+
337
+ var snapshot = {type: 'json0', id: 'test2', v: 1, data: {foo: 'bar'}};
338
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
339
+ if (err) return done(err);
340
+ db.getOpsBulk('testcollection', {
341
+ test2: 0
342
+ }, {
343
+ test2: 1
344
+ }, {testOptions: 'yes'}, function(err) {
345
+ if (err) return done(err);
346
+ /*
347
+ Don't finalize the test in the middleware - since getOps will make queries *after* the middleware is fired.
348
+ If we call done() in the middleware, we'll close the db connection, and then getOps will call _getOps()
349
+ which will throw a "db connection closed" error.
350
+ */
351
+ expect(middlewareSpy).to.have.been.calledOnceWith(sinon.match.object, sinon.match.func);
352
+ done();
353
+ });
354
+ });
355
+ });
356
+
357
+ it('has the expected properties on the request object before getting bulk snapshots', function(done) {
358
+ db.use(BEFORE_SNAPSHOT_LOOKUP, function(request, next) {
359
+ expect(request).to.have.all.keys([
360
+ 'action',
361
+ 'collectionName',
362
+ 'options',
363
+ 'query'
364
+ ]);
365
+ expect(request.action).to.equal(BEFORE_SNAPSHOT_LOOKUP);
366
+ expect(request.collectionName).to.equal('testcollection');
367
+ expect(request.options.testOptions).to.equal('yes');
368
+ expect(request.query._id).to.deep.equal({$in: ['test1']});
369
+ next();
370
+ done();
371
+ });
372
+
373
+ var snapshot = {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}};
374
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, function(err) {
375
+ if (err) return done(err);
376
+ db.getSnapshotBulk('testcollection', ['test1'], null, {testOptions: 'yes'}, function(err, doc) {
377
+ if (err) return done(err);
378
+ expect(doc).to.exist;
379
+ });
380
+ });
381
+ });
382
+
383
+ it('should augment the query when getSnapshot is called', function(done) {
384
+ var snapshots = [
385
+ {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}},
386
+ {type: 'json0', id: 'test2', v: 1, data: {foo: 'baz'}}
387
+ ];
388
+
389
+ async.each(snapshots, function(snapshot, cb) {
390
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, cb);
391
+ }, function(err) {
392
+ if (err) return done(err);
393
+ db.getSnapshot('testcollection', 'test1', null, null, function(err, doc) {
394
+ if (err) return done(err);
395
+ expect(doc.data).eql({
396
+ foo: 'bar'
397
+ });
398
+
399
+ // Change the query to look for baz and not bar
400
+ db.use(BEFORE_SNAPSHOT_LOOKUP, function(request, next) {
401
+ request.query = {_id: 'test2'};
402
+ next();
403
+ });
404
+
405
+ db.getSnapshot('testcollection', 'test1', null, null, function(err, doc) {
406
+ if (err) return done(err);
407
+ expect(doc.data).eql({
408
+ foo: 'baz'
409
+ });
410
+ done();
411
+ });
412
+ });
413
+ });
414
+ });
415
+
416
+ it('should augment the query when getSnapshotBulk is called', function(done) {
417
+ var snapshots = [
418
+ {type: 'json0', id: 'test1', v: 1, data: {foo: 'bar'}},
419
+ {type: 'json0', id: 'test2', v: 1, data: {foo: 'baz'}}
420
+ ];
421
+
422
+ async.each(snapshots, function(snapshot, cb) {
423
+ db.commit('testcollection', snapshot.id, {v: 0, create: {}}, snapshot, null, cb);
424
+ }, function(err) {
425
+ if (err) return done(err);
426
+ db.getSnapshotBulk('testcollection', ['test1', 'test2'], null, null, function(err, docs) {
427
+ if (err) return done(err);
428
+ expect(docs.test1.data.foo).to.equal('bar');
429
+ expect(docs.test2.data.foo).to.equal('baz');
430
+
431
+ // Change the query to look for baz and not bar
432
+ db.use(BEFORE_SNAPSHOT_LOOKUP, function(request, next) {
433
+ request.query = {_id: {$in: ['test2']}};
434
+ next();
435
+ });
436
+
437
+ db.getSnapshotBulk('testcollection', ['test1', 'test2'], null, null, function(err, docs) {
438
+ if (err) return done(err);
439
+ expect(docs.test1.data).not.to.exist;
440
+ expect(docs.test2.data.foo).to.equal('baz');
441
+ done();
442
+ });
443
+ });
444
+ });
445
+ });
446
+ });
447
+
448
+ function expectDocumentToContainFoo(valueOfFoo, cb) {
449
+ var query = {_id: 'test1'};
450
+
451
+ db.query('testcollection', query, null, null, function(err, results) {
452
+ if (err) return done(err);
453
+ expect(results[0].data).eql({
454
+ foo: valueOfFoo
455
+ });
456
+ cb();
457
+ });
458
+ };
459
+
460
+ function expectDocumentNotToExist(cb) {
461
+ var query = {_id: 'test1'};
462
+
463
+ db.query('testcollection', query, null, null, function(err, results) {
464
+ if (err) return cb(err);
465
+ expect(results).to.be.empty;
466
+ cb();
467
+ });
468
+ };
469
+ });
@@ -0,0 +1,159 @@
1
+ var OpLinkValidator = require('../op-link-validator');
2
+ var expect = require('chai').expect;
3
+
4
+ describe('OpLinkValidator', function() {
5
+ it('starts with no unique op', function() {
6
+ var validator = new OpLinkValidator();
7
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
8
+ expect(opWithUniqueVersion).to.equal(null);
9
+ });
10
+
11
+ it('starts not at the end of the list', function() {
12
+ var validator = new OpLinkValidator();
13
+ expect(validator.isAtEndOfList()).to.equal(false);
14
+ });
15
+
16
+ it('has no unique op with just one op', function() {
17
+ var op = {v: 1};
18
+ var validator = new OpLinkValidator();
19
+
20
+ validator.push(op);
21
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
22
+
23
+ expect(opWithUniqueVersion).to.equal(null);
24
+ });
25
+
26
+ it('has a unique op with just two different ops', function() {
27
+ var op1 = {v: 1};
28
+ var op2 = {v: 2};
29
+ var validator = new OpLinkValidator();
30
+
31
+ validator.push(op1);
32
+ validator.push(op2);
33
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
34
+
35
+ expect(opWithUniqueVersion).to.equal(op1);
36
+ });
37
+
38
+ it('does not have a uniquye op with just two identical ops', function() {
39
+ var op1 = {v: 1};
40
+ var op2 = {v: 1};
41
+ var validator = new OpLinkValidator();
42
+
43
+ validator.push(op1);
44
+ validator.push(op2);
45
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
46
+
47
+ expect(opWithUniqueVersion).to.equal(null);
48
+ });
49
+
50
+ it('has a unique op with three ops with different versions', function() {
51
+ var op1 = {v: 1};
52
+ var op2 = {v: 2};
53
+ var op3 = {v: 3};
54
+ var validator = new OpLinkValidator();
55
+
56
+ validator.push(op1);
57
+ validator.push(op2);
58
+ validator.push(op3);
59
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
60
+
61
+ expect(opWithUniqueVersion).to.equal(op2);
62
+ });
63
+
64
+ it('is not at the end of the list with three ops', function() {
65
+ var op1 = {v: 1};
66
+ var op2 = {v: 2};
67
+ var op3 = {v: 3};
68
+ var validator = new OpLinkValidator();
69
+
70
+ validator.push(op1);
71
+ validator.push(op2);
72
+ validator.push(op3);
73
+
74
+ expect(validator.isAtEndOfList()).to.equal(false);
75
+ });
76
+
77
+ it('does not have a unique op with three ops with the same version', function() {
78
+ var op = {v: 1};
79
+ var validator = new OpLinkValidator();
80
+
81
+ validator.push(op);
82
+ validator.push(op);
83
+ validator.push(op);
84
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
85
+
86
+ expect(opWithUniqueVersion).to.equal(null);
87
+ });
88
+
89
+ it('does not have a unique op if the first two ops are the same', function() {
90
+ var op1 = {v: 1};
91
+ var op2 = {v: 1};
92
+ var op3 = {v: 2};
93
+ var validator = new OpLinkValidator();
94
+
95
+ validator.push(op1);
96
+ validator.push(op2);
97
+ validator.push(op3);
98
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
99
+
100
+ expect(opWithUniqueVersion).to.equal(null);
101
+ });
102
+
103
+ it('does not have a unique op if the last two ops are the same', function() {
104
+ var op1 = {v: 1};
105
+ var op2 = {v: 2};
106
+ var op3 = {v: 2};
107
+ var validator = new OpLinkValidator();
108
+
109
+ validator.push(op1);
110
+ validator.push(op2);
111
+ validator.push(op3);
112
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
113
+
114
+ expect(opWithUniqueVersion).to.equal(null);
115
+ });
116
+
117
+ it('has a unique op in a long chain', function() {
118
+ var op1 = {v: 1};
119
+ var op2 = {v: 1};
120
+ var op3 = {v: 1};
121
+ var op4 = {v: 2};
122
+ var op5 = {v: 2};
123
+ var op6 = {v: 3};
124
+ var op7 = {v: 4};
125
+ var validator = new OpLinkValidator();
126
+
127
+ validator.push(op1);
128
+ validator.push(op2);
129
+ validator.push(op3);
130
+ validator.push(op4);
131
+ validator.push(op5);
132
+ validator.push(op6);
133
+ validator.push(op7);
134
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
135
+
136
+ expect(opWithUniqueVersion).to.equal(op6);
137
+ });
138
+
139
+ it('has a unique op with two ops and a current op of null', function() {
140
+ var op1 = {v: 1};
141
+ var op2 = {v: 2};
142
+ var op3 = null;
143
+ var validator = new OpLinkValidator();
144
+
145
+ validator.push(op1);
146
+ validator.push(op2);
147
+ validator.push(op3);
148
+ var opWithUniqueVersion = validator.opWithUniqueVersion();
149
+
150
+ expect(opWithUniqueVersion).to.equal(op2);
151
+ });
152
+
153
+ it('is at the end of the list with a current op of null', function() {
154
+ var op = null;
155
+ var validator = new OpLinkValidator();
156
+ validator.push(op);
157
+ expect(validator.isAtEndOfList()).to.equal(true);
158
+ });
159
+ });
@@ -1,6 +1,5 @@
1
- var expect = require('expect.js');
1
+ var expect = require('chai').expect;
2
2
  var ShareDbMongo = require('../index');
3
- var checkOp = require('sharedb/lib/ot').checkOp;
4
3
 
5
4
  describe('skipPoll', function() {
6
5
  // Run a test function against a small sample set of queries
@@ -8,7 +7,7 @@ describe('skipPoll', function() {
8
7
  function testInNewCase(query) {
9
8
  it(JSON.stringify(query), function() {
10
9
  test(query);
11
- })
10
+ });
12
11
  };
13
12
 
14
13
  testInNewCase({a: 1});
@@ -129,8 +128,12 @@ function assertIfSkips(rawOp, query, expectedSkips) {
129
128
  expect(actualSkips).eql(expectedSkips);
130
129
  }
131
130
 
132
- function assertSkips(rawOp, query) { assertIfSkips(rawOp, query, true); };
133
- function assertNotSkips(rawOp, query) { assertIfSkips(rawOp, query, false); };
131
+ function assertSkips(rawOp, query) {
132
+ assertIfSkips(rawOp, query, true);
133
+ };
134
+ function assertNotSkips(rawOp, query) {
135
+ assertIfSkips(rawOp, query, false);
136
+ };
134
137
 
135
138
  function has(haystack, needle) {
136
139
  return haystack.indexOf(needle) !== -1;
package/.npmignore DELETED
@@ -1,4 +0,0 @@
1
- *.swp
2
- *.DS_Store
3
- node_modules
4
- coverage
package/.travis.yml DELETED
@@ -1,27 +0,0 @@
1
- language: node_js
2
-
3
- node_js:
4
- - "6"
5
- - "8"
6
- - "10"
7
-
8
- services:
9
- - docker
10
-
11
- env:
12
- - MONGODB_VERSION="2.6"
13
- - MONGODB_VERSION="3.6"
14
- - MONGODB_VERSION="4.0"
15
-
16
- before_install:
17
- - docker run -d -p 127.0.0.1:27017:27017 mongo:$MONGODB_VERSION
18
-
19
- before_script:
20
- - until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done
21
-
22
- script:
23
- - npm run test-cover
24
-
25
- # Send coverage data to Coveralls
26
- after_script:
27
- - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js