diff --git a/lib/client/doc.js b/lib/client/doc.js index dcd48ec9..d3713492 100644 --- a/lib/client/doc.js +++ b/lib/client/doc.js @@ -968,11 +968,11 @@ Doc.prototype._opAcknowledged = function(message) { } if (message[ACTIONS.fixup]) { - for (var i = 0; i < message[ACTIONS.fixup].length; i++) { - var fixupOp = message[ACTIONS.fixup][i]; + for (var fixupIndex = 0; fixupIndex < message[ACTIONS.fixup].length; fixupIndex++) { + var fixupOp = message[ACTIONS.fixup][fixupIndex]; - for (var j = 0; j < this.pendingOps.length; j++) { - var transformErr = transformX(this.pendingOps[i], fixupOp); + for (var pendingIndex = 0; pendingIndex < this.pendingOps.length; pendingIndex++) { + var transformErr = transformX(this.pendingOps[pendingIndex], fixupOp); if (transformErr) return this._hardRollback(transformErr); } diff --git a/test/middleware.js b/test/middleware.js index 66e50b2f..6f87c2f8 100644 --- a/test/middleware.js +++ b/test/middleware.js @@ -565,6 +565,68 @@ describe('middleware', function() { }); }); + it('transforms a pending op by multiple fixups', function(done) { + var applied = false; + backend.use('apply', function(request, next) { + if (applied) return next(); + applied = true; + request.$fixup([{p: ['tricks', 0], li: 'sit'}]); + request.$fixup([{p: ['tricks', 0], li: 'stay'}]); + next(); + }); + + var remoteConnection = backend.connect(); + var remoteDoc = remoteConnection.get('dogs', 'fido'); + + remoteDoc.subscribe(function(error) { + if (error) return done(error); + + expect(remoteDoc.data).to.eql({name: 'fido'}); + + remoteDoc.on('op batch', function() { + if (remoteDoc.version !== 3) return; + expect(remoteDoc.data.tricks).to.eql(['stay', 'sit', 'fetch', 'lie down']); + expect(remoteDoc.data).to.eql(doc.data); + done(); + }); + + doc.preventCompose = true; + doc.submitOp([{p: ['tricks'], oi: ['fetch']}], errorHandler(done)); + doc.submitOp([{p: ['tricks', 1], li: 'lie down'}], errorHandler(done)); + }); + }); + + it('transforms multiple pending ops by a fixup', function(done) { + var applied = false; + backend.use('apply', function(request, next) { + if (applied) return next(); + applied = true; + request.$fixup([{p: ['tricks', 0], li: 'stay'}]); + next(); + }); + + var remoteConnection = backend.connect(); + var remoteDoc = remoteConnection.get('dogs', 'fido'); + + remoteDoc.subscribe(function(error) { + if (error) return done(error); + + expect(remoteDoc.data).to.eql({name: 'fido'}); + + remoteDoc.on('op batch', function() { + if (remoteDoc.version !== 4) return; + expect(remoteDoc.data.tricks).to.eql(['stay', 'fetch', 'sit', 'roll over']); + expect(remoteDoc.data).to.eql(doc.data); + done(); + }); + + doc.preventCompose = true; + doc.submitOp([{p: ['tricks'], oi: ['fetch']}], errorHandler(done)); + doc.submitOp([{p: ['tricks', 1], li: 'sit'}], errorHandler(done)); + doc.submitOp([{p: ['tricks', 2], li: 'roll over'}], errorHandler(done)); + }); + }); + it('applies a fixup to a creation op', function(done) { backend.use('apply', function(request, next) { request.$fixup([{p: ['goodBoy'], oi: true}]);