@@ -2011,114 +2011,239 @@ describe('store', function () {
20112011
20122012 describe ( '#findAndModifyWithFLEFallback' , function ( ) {
20132013 let dataServiceStub ;
2014+ let findFake ;
2015+ let findOneAndReplaceFake ;
2016+ let findOneAndUpdateFake ;
2017+ let updateOneFake ;
2018+ let replaceOneFake ;
2019+
2020+ const document = { _id : 1234 , name : 'document_1234' } ;
2021+ const updatedDocument = { _id : 1234 , name : 'document_12345' } ;
20142022
20152023 beforeEach ( function ( ) {
2024+ findFake = sinon . stub ( ) ;
2025+ findOneAndReplaceFake = sinon . stub ( ) ;
2026+ findOneAndUpdateFake = sinon . stub ( ) ;
2027+ updateOneFake = sinon . stub ( ) ;
2028+ replaceOneFake = sinon . stub ( ) ;
20162029 dataServiceStub = {
2017- find : sinon . stub ( ) . callsFake ( ( ns , query ) => Promise . resolve ( [ query ] ) ) ,
2030+ find : findFake ,
2031+ findOneAndReplace : findOneAndReplaceFake ,
2032+ findOneAndUpdate : findOneAndUpdateFake ,
2033+ updateOne : updateOneFake ,
2034+ replaceOne : replaceOneFake ,
20182035 } ;
20192036 } ) ;
20202037
2021- it ( 'does the original findAndModify operation and nothing more if it succeeds' , async function ( ) {
2022- const document = { _id : 1234 } ;
2023- const stub = sinon . stub ( ) . callsFake ( ( ) => {
2024- return [ undefined , document ] ;
2038+ afterEach ( function ( ) {
2039+ sinon . restore ( ) ;
2040+ } ) ;
2041+
2042+ it ( 'does the original findOneAndUpdate operation and nothing more if it succeeds' , async function ( ) {
2043+ findFake . callsFake ( ( ) => Promise . resolve ( [ ] ) ) ;
2044+ findOneAndReplaceFake . resolves ( { } ) ;
2045+ findOneAndUpdateFake . resolves ( updatedDocument ) ;
2046+ const [ error , d ] = await findAndModifyWithFLEFallback (
2047+ dataServiceStub ,
2048+ 'db.coll' ,
2049+ { _id : 1234 } as any ,
2050+ { name : 'document_12345' } ,
2051+ 'update'
2052+ ) ;
2053+ expect ( error ) . to . equal ( undefined ) ;
2054+ expect ( d ) . to . equal ( updatedDocument ) ;
2055+ expect ( findOneAndReplaceFake ) . to . have . callCount ( 0 ) ;
2056+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 1 ) ;
2057+ expect ( findOneAndUpdateFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2058+ expect ( findOneAndUpdateFake . firstCall . args [ 1 ] ) . to . deep . equal ( {
2059+ _id : 1234 ,
2060+ } ) ;
2061+ expect ( findOneAndUpdateFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2062+ name : 'document_12345' ,
2063+ } ) ;
2064+ expect ( findOneAndUpdateFake . firstCall . args [ 3 ] ) . to . deep . equal ( {
2065+ returnDocument : 'after' ,
2066+ promoteValues : false ,
20252067 } ) ;
2068+ } ) ;
2069+
2070+ it ( 'does the original findOneAndReplace operation and nothing more if it succeeds' , async function ( ) {
2071+ findFake . callsFake ( ( ) => Promise . resolve ( [ ] ) ) ;
2072+ findOneAndReplaceFake . resolves ( updatedDocument ) ;
2073+ findOneAndUpdateFake . resolves ( { } ) ;
20262074 const [ error , d ] = await findAndModifyWithFLEFallback (
20272075 dataServiceStub ,
20282076 'db.coll' ,
2029- stub
2077+ { _id : 1234 } as any ,
2078+ { name : 'document_12345' } ,
2079+ 'replace'
20302080 ) ;
20312081 expect ( error ) . to . equal ( undefined ) ;
2032- expect ( d ) . to . equal ( document ) ;
2033- expect ( stub ) . to . have . callCount ( 1 ) ;
2034- expect ( stub . firstCall . args [ 0 ] ) . to . equal ( dataServiceStub ) ;
2035- expect ( stub . firstCall . args [ 1 ] ) . to . equal ( 'db.coll' ) ;
2036- expect ( stub . firstCall . args [ 2 ] ) . to . deep . equal ( {
2082+ expect ( d ) . to . equal ( updatedDocument ) ;
2083+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 0 ) ;
2084+ expect ( findOneAndReplaceFake ) . to . have . callCount ( 1 ) ;
2085+ expect ( findOneAndReplaceFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2086+ expect ( findOneAndReplaceFake . firstCall . args [ 1 ] ) . to . deep . equal ( {
2087+ _id : 1234 ,
2088+ } ) ;
2089+ expect ( findOneAndReplaceFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2090+ name : 'document_12345' ,
2091+ } ) ;
2092+ expect ( findOneAndReplaceFake . firstCall . args [ 3 ] ) . to . deep . equal ( {
20372093 returnDocument : 'after' ,
20382094 promoteValues : false ,
20392095 } ) ;
20402096 } ) ;
20412097
2042- it ( 'does the original findAndModify operation and nothing more if it fails with a non-FLE error' , async function ( ) {
2098+ it ( 'does the original findOneAndUpdate operation and nothing more if it fails with a non-FLE error' , async function ( ) {
20432099 const err = new Error ( 'failed' ) ;
2044- const stub = sinon . stub ( ) . callsFake ( ( ) => {
2045- return [ err ] ;
2046- } ) ;
2100+ findFake . callsFake ( ( ) => Promise . resolve ( [ ] ) ) ;
2101+ findOneAndReplaceFake . resolves ( { } ) ;
2102+ findOneAndUpdateFake . rejects ( err ) ;
20472103 const [ error , d ] = await findAndModifyWithFLEFallback (
20482104 dataServiceStub ,
20492105 'db.coll' ,
2050- stub
2106+ { _id : 1234 } as any ,
2107+ { name : 'document_12345' } ,
2108+ 'update'
20512109 ) ;
20522110 expect ( error ) . to . equal ( err ) ;
20532111 expect ( d ) . to . equal ( undefined ) ;
2054- expect ( stub ) . to . have . callCount ( 1 ) ;
2055- expect ( stub . firstCall . args [ 0 ] ) . to . equal ( dataServiceStub ) ;
2056- expect ( stub . firstCall . args [ 1 ] ) . to . equal ( 'db.coll' ) ;
2057- expect ( stub . firstCall . args [ 2 ] ) . to . deep . equal ( {
2112+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 1 ) ;
2113+ expect ( findOneAndUpdateFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2114+ expect ( findOneAndUpdateFake . firstCall . args [ 1 ] ) . to . deep . equal ( {
2115+ _id : 1234 ,
2116+ } ) ;
2117+ expect ( findOneAndUpdateFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2118+ name : 'document_12345' ,
2119+ } ) ;
2120+ expect ( findOneAndUpdateFake . firstCall . args [ 3 ] ) . to . deep . equal ( {
20582121 returnDocument : 'after' ,
20592122 promoteValues : false ,
20602123 } ) ;
20612124 } ) ;
20622125
2063- it ( 'retries findAndModify with FLE returnDocument: "after"' , async function ( ) {
2064- const document = { _id : 1234 } ;
2126+ it ( 'retries findOneAndUpdate with FLE returnDocument: "after"' , async function ( ) {
20652127 const err = Object . assign ( new Error ( 'failed' ) , { code : 6371402 } ) ;
2066- const stub = sinon . stub ( ) ;
2067- stub . onFirstCall ( ) . callsFake ( ( ) => {
2068- return [ err ] ;
2069- } ) ;
2070- stub . onSecondCall ( ) . callsFake ( ( ) => {
2071- return [ undefined , document ] ;
2072- } ) ;
2128+ findFake . callsFake ( ( ) => Promise . resolve ( [ updatedDocument ] ) ) ;
2129+ findOneAndReplaceFake . resolves ( { } ) ;
2130+ findOneAndUpdateFake . onCall ( 0 ) . rejects ( err ) ;
2131+ findOneAndUpdateFake . onCall ( 1 ) . resolves ( document ) ;
20732132 const [ error , d ] = await findAndModifyWithFLEFallback (
20742133 dataServiceStub ,
20752134 'db.coll' ,
2076- stub
2135+ { _id : 1234 } as any ,
2136+ { name : 'document_12345' } ,
2137+ 'update'
20772138 ) ;
20782139 expect ( error ) . to . equal ( undefined ) ;
2079- expect ( d ) . to . deep . equal ( document ) ;
2080- expect ( stub ) . to . have . callCount ( 2 ) ;
2081- expect ( stub . firstCall . args [ 0 ] ) . to . equal ( dataServiceStub ) ;
2082- expect ( stub . firstCall . args [ 1 ] ) . to . equal ( 'db.coll' ) ;
2083- expect ( stub . firstCall . args [ 2 ] ) . to . deep . equal ( {
2140+ expect ( d ) . to . deep . equal ( updatedDocument ) ;
2141+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 2 ) ;
2142+
2143+ expect ( findOneAndUpdateFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2144+ expect ( findOneAndUpdateFake . firstCall . args [ 1 ] ) . to . deep . equal ( {
2145+ _id : 1234 ,
2146+ } ) ;
2147+ expect ( findOneAndUpdateFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2148+ name : 'document_12345' ,
2149+ } ) ;
2150+ expect ( findOneAndUpdateFake . firstCall . args [ 3 ] ) . to . deep . equal ( {
20842151 returnDocument : 'after' ,
20852152 promoteValues : false ,
20862153 } ) ;
2087- expect ( stub . secondCall . args [ 0 ] ) . to . equal ( dataServiceStub ) ;
2088- expect ( stub . secondCall . args [ 1 ] ) . to . equal ( 'db.coll' ) ;
2089- expect ( stub . secondCall . args [ 2 ] ) . to . deep . equal ( {
2154+
2155+ expect ( findOneAndUpdateFake . secondCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2156+ expect ( findOneAndUpdateFake . secondCall . args [ 1 ] ) . to . deep . equal ( {
2157+ _id : 1234 ,
2158+ } ) ;
2159+ expect ( findOneAndUpdateFake . secondCall . args [ 2 ] ) . to . deep . equal ( {
2160+ name : 'document_12345' ,
2161+ } ) ;
2162+ expect ( findOneAndUpdateFake . secondCall . args [ 3 ] ) . to . deep . equal ( {
20902163 returnDocument : 'before' ,
20912164 promoteValues : false ,
20922165 } ) ;
2093- expect ( dataServiceStub . find ) . to . have . callCount ( 1 ) ;
2094- expect ( dataServiceStub . find . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2095- expect ( dataServiceStub . find . firstCall . args [ 1 ] ) . to . deep . equal ( document ) ;
2096- expect ( dataServiceStub . find . firstCall . args [ 2 ] ) . to . deep . equal ( {
2166+
2167+ expect ( findFake ) . to . have . callCount ( 1 ) ;
2168+ expect ( findFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2169+ expect ( findFake . firstCall . args [ 1 ] ) . to . deep . equal ( { _id : 1234 } ) ;
2170+ expect ( findFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
20972171 returnDocument : 'before' ,
20982172 promoteValues : false ,
20992173 } ) ;
21002174 } ) ;
21012175
21022176 it ( 'returns the original error if the fallback find operation fails' , async function ( ) {
2103- dataServiceStub . find . yields ( new Error ( 'find failed' ) ) ;
2104- const document = { _id : 1234 } ;
21052177 const err = Object . assign ( new Error ( 'failed' ) , { code : 6371402 } ) ;
2106- const stub = sinon . stub ( ) ;
2107- stub . onFirstCall ( ) . callsFake ( ( ) => {
2108- return [ err ] ;
2109- } ) ;
2110- stub . onSecondCall ( ) . callsFake ( ( ) => {
2111- return [ undefined , document ] ;
2112- } ) ;
2178+ findFake . yields ( new Error ( 'find failed' ) ) ;
2179+ findOneAndReplaceFake . resolves ( { } ) ;
2180+ findOneAndUpdateFake . onCall ( 0 ) . rejects ( err ) ;
2181+ findOneAndUpdateFake . onCall ( 1 ) . resolves ( document ) ;
21132182 const [ error , d ] = await findAndModifyWithFLEFallback (
21142183 dataServiceStub ,
21152184 'db.coll' ,
2116- stub
2185+ { _id : 1234 } as any ,
2186+ { name : 'document_12345' } ,
2187+ 'update'
21172188 ) ;
21182189 expect ( error ) . to . equal ( err ) ;
21192190 expect ( d ) . to . equal ( undefined ) ;
2120- expect ( stub ) . to . have . callCount ( 2 ) ;
2121- expect ( dataServiceStub . find ) . to . have . callCount ( 1 ) ;
2191+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 2 ) ;
2192+ expect ( findFake ) . to . have . callCount ( 1 ) ;
2193+ } ) ;
2194+
2195+ it ( 'calls updateOne if findOneAndUpdate returns the ShardKeyNotFound error' , async function ( ) {
2196+ const err = Object . assign (
2197+ new Error ( 'Query for sharded findAndModify must contain the shard key' ) ,
2198+ { codeName : 'ShardKeyNotFound' }
2199+ ) ;
2200+ findFake . callsFake ( ( ) => Promise . resolve ( [ updatedDocument ] ) ) ;
2201+ findOneAndReplaceFake . resolves ( { } ) ;
2202+ findOneAndUpdateFake . rejects ( err ) ;
2203+ updateOneFake . resolves ( updatedDocument ) ;
2204+ const [ error , d ] = await findAndModifyWithFLEFallback (
2205+ dataServiceStub ,
2206+ 'db.coll' ,
2207+ { _id : 1234 } as any ,
2208+ { name : 'document_12345' } ,
2209+ 'update'
2210+ ) ;
2211+ expect ( error ) . to . equal ( undefined ) ;
2212+ expect ( d ) . to . equal ( updatedDocument ) ;
2213+ expect ( findOneAndUpdateFake ) . to . have . callCount ( 1 ) ;
2214+ expect ( updateOneFake ) . to . have . callCount ( 1 ) ;
2215+ expect ( updateOneFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2216+ expect ( updateOneFake . firstCall . args [ 1 ] ) . to . deep . equal ( { _id : 1234 } ) ;
2217+ expect ( updateOneFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2218+ name : 'document_12345' ,
2219+ } ) ;
2220+ } ) ;
2221+
2222+ it ( 'calls replaceOne if findOneAndReplace returns the ShardKeyNotFound error' , async function ( ) {
2223+ const err = Object . assign (
2224+ new Error ( 'Query for sharded findAndModify must contain the shard key' ) ,
2225+ { codeName : 'ShardKeyNotFound' }
2226+ ) ;
2227+ findFake . callsFake ( ( ) => Promise . resolve ( [ updatedDocument ] ) ) ;
2228+ findOneAndReplaceFake . rejects ( err ) ;
2229+ findOneAndUpdateFake . resolves ( { } ) ;
2230+ replaceOneFake . resolves ( updatedDocument ) ;
2231+ const [ error , d ] = await findAndModifyWithFLEFallback (
2232+ dataServiceStub ,
2233+ 'db.coll' ,
2234+ { _id : 1234 } as any ,
2235+ { name : 'document_12345' } ,
2236+ 'replace'
2237+ ) ;
2238+ expect ( error ) . to . equal ( undefined ) ;
2239+ expect ( d ) . to . equal ( updatedDocument ) ;
2240+ expect ( findOneAndReplaceFake ) . to . have . callCount ( 1 ) ;
2241+ expect ( replaceOneFake ) . to . have . callCount ( 1 ) ;
2242+ expect ( replaceOneFake . firstCall . args [ 0 ] ) . to . equal ( 'db.coll' ) ;
2243+ expect ( replaceOneFake . firstCall . args [ 1 ] ) . to . deep . equal ( { _id : 1234 } ) ;
2244+ expect ( replaceOneFake . firstCall . args [ 2 ] ) . to . deep . equal ( {
2245+ name : 'document_12345' ,
2246+ } ) ;
21222247 } ) ;
21232248 } ) ;
21242249} ) ;
0 commit comments