@@ -2,8 +2,10 @@ var async = require('async');
22var expect = require ( 'expect.js' ) ;
33var types = require ( '../../lib/types' ) ;
44var deserializedType = require ( './deserialized-type' ) ;
5+ var numberType = require ( './number-type' ) ;
56types . register ( deserializedType . type ) ;
67types . register ( deserializedType . type2 ) ;
8+ types . register ( numberType . type ) ;
79
810module . exports = function ( ) {
911describe ( 'client submit' , function ( ) {
@@ -509,25 +511,44 @@ describe('client submit', function() {
509511 } ) ;
510512
511513 it ( 'submits fail above the backend.maxSubmitRetries threshold' , function ( done ) {
514+ var backend = this . backend ;
512515 this . backend . maxSubmitRetries = 0 ;
513516 var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
514517 var doc2 = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
515518 doc . create ( { age : 3 } , function ( err ) {
516519 if ( err ) return done ( err ) ;
517520 doc2 . fetch ( function ( err ) {
518521 if ( err ) return done ( err ) ;
519- var count = 0 ;
520- var cb = function ( err ) {
521- count ++ ;
522- if ( count === 1 ) {
523- if ( err ) return done ( err ) ;
524- } else {
525- expect ( err ) . ok ( ) ;
526- done ( ) ;
522+ var docCallback ;
523+ var doc2Callback ;
524+ // The submit retry happens just after an op is committed. This hook into the middleware
525+ // catches both ops just before they're about to be committed. This ensures that both ops
526+ // are certainly working on the same snapshot (ie one op hasn't been committed before the
527+ // other fetches the snapshot to apply to). By storing the callbacks, we can then
528+ // manually trigger the callbacks, first calling doc, and when we know that's been committed,
529+ // we then commit doc2.
530+ backend . use ( 'commit' , function ( request , callback ) {
531+ if ( request . op . op [ 0 ] . na === 2 ) docCallback = callback ;
532+ if ( request . op . op [ 0 ] . na === 7 ) doc2Callback = callback ;
533+
534+ // Wait until both ops have been applied to the same snapshot and are about to be committed
535+ if ( docCallback && doc2Callback ) {
536+ // Trigger the first op's commit and then the second one later, which will cause the
537+ // second op to retry
538+ docCallback ( ) ;
527539 }
528- } ;
529- doc . submitOp ( { p : [ 'age' ] , na : 2 } , cb ) ;
530- doc2 . submitOp ( { p : [ 'age' ] , na : 7 } , cb ) ;
540+ } ) ;
541+ doc . submitOp ( { p : [ 'age' ] , na : 2 } , function ( error ) {
542+ if ( error ) return done ( error ) ;
543+ // When we know the first op has been committed, we try to commit the second op, which will
544+ // fail because it's working on an out-of-date snapshot. It will retry, but exceed the
545+ // maxSubmitRetries limit of 0
546+ doc2Callback ( ) ;
547+ } ) ;
548+ doc2 . submitOp ( { p : [ 'age' ] , na : 7 } , function ( error ) {
549+ expect ( error ) . ok ( ) ;
550+ done ( ) ;
551+ } ) ;
531552 } ) ;
532553 } ) ;
533554 } ) ;
@@ -608,11 +629,16 @@ describe('client submit', function() {
608629 doc2 . del ( function ( err ) {
609630 if ( err ) return done ( err ) ;
610631 doc . pause ( ) ;
632+ var calledBack = false ;
633+ doc . on ( 'error' , function ( ) {
634+ expect ( calledBack ) . equal ( true ) ;
635+ done ( ) ;
636+ } ) ;
611637 doc . submitOp ( { p : [ 'age' ] , na : 1 } , function ( err ) {
612638 expect ( err ) . ok ( ) ;
613639 expect ( doc . version ) . equal ( 2 ) ;
614640 expect ( doc . data ) . eql ( undefined ) ;
615- done ( ) ;
641+ calledBack = true ;
616642 } ) ;
617643 doc . fetch ( ) ;
618644 } ) ;
@@ -632,11 +658,16 @@ describe('client submit', function() {
632658 doc2 . create ( { age : 5 } , function ( err ) {
633659 if ( err ) return done ( err ) ;
634660 doc . pause ( ) ;
661+ var calledBack = false ;
662+ doc . on ( 'error' , function ( ) {
663+ expect ( calledBack ) . equal ( true ) ;
664+ done ( ) ;
665+ } ) ;
635666 doc . create ( { age : 9 } , function ( err ) {
636667 expect ( err ) . ok ( ) ;
637668 expect ( doc . version ) . equal ( 3 ) ;
638669 expect ( doc . data ) . eql ( { age : 5 } ) ;
639- done ( ) ;
670+ calledBack = true ;
640671 } ) ;
641672 doc . fetch ( ) ;
642673 } ) ;
@@ -1044,6 +1075,19 @@ describe('client submit', function() {
10441075 } ) ;
10451076 } ) ;
10461077
1078+ it ( 'allows snapshot and op to be a non-object' , function ( done ) {
1079+ var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
1080+ doc . create ( 5 , numberType . type . uri , function ( err ) {
1081+ if ( err ) return done ( err ) ;
1082+ expect ( doc . data ) . to . equal ( 5 ) ;
1083+ doc . submitOp ( 2 , function ( err ) {
1084+ if ( err ) return done ( err ) ;
1085+ expect ( doc . data ) . to . equal ( 7 ) ;
1086+ done ( ) ;
1087+ } ) ;
1088+ } ) ;
1089+ } ) ;
1090+
10471091 describe ( 'type.deserialize' , function ( ) {
10481092 it ( 'can create a new doc' , function ( done ) {
10491093 var doc = this . backend . connect ( ) . get ( 'dogs' , 'fido' ) ;
0 commit comments