@@ -10,7 +10,7 @@ vi.mock('@/lib/mongodb', () => ({
1010
1111vi . mock ( '@/models/User' , ( ) => ( {
1212 User : {
13- findOneAndUpdate : vi . fn ( ) ,
13+ updateOne : vi . fn ( ) ,
1414 } ,
1515} ) ) ;
1616
@@ -98,10 +98,10 @@ describe('POST /api/track-user', () => {
9898 expect ( dbConnect ) . toHaveBeenCalled ( ) ;
9999
100100 // Trims and lowercases
101- expect ( User . findOneAndUpdate ) . toHaveBeenCalledWith (
101+ expect ( User . updateOne ) . toHaveBeenCalledWith (
102102 { username : 'octocat' } ,
103103 { $setOnInsert : { username : 'octocat' } } ,
104- { upsert : true , new : true }
104+ { upsert : true }
105105 ) ;
106106
107107 expect ( response . status ) . toBe ( 200 ) ;
@@ -123,5 +123,50 @@ describe('POST /api/track-user', () => {
123123
124124 consoleErrorSpy . mockRestore ( ) ;
125125 } ) ;
126+
127+ it ( 'gracefully handles concurrent duplicate key (code 11000) race conditions' , async ( ) => {
128+ const consoleErrorSpy = vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
129+
130+ const mongoError = new Error ( 'E11000 duplicate key error collection: username' ) as Error & {
131+ code ?: number ;
132+ keyPattern ?: Record < string , number > ;
133+ } ;
134+ mongoError . code = 11000 ;
135+ mongoError . keyPattern = { username : 1 } ;
136+ vi . mocked ( User . updateOne ) . mockRejectedValueOnce ( mongoError ) ;
137+
138+ const response = await POST ( makeRequest ( { username : 'octocat' } ) ) ;
139+
140+ expect ( response . status ) . toBe ( 200 ) ;
141+ const data = await response . json ( ) ;
142+ expect ( data . success ) . toBe ( true ) ;
143+ expect ( consoleErrorSpy ) . not . toHaveBeenCalled ( ) ;
144+
145+ consoleErrorSpy . mockRestore ( ) ;
146+ } ) ;
147+
148+ it ( 'rethrows duplicate key (code 11000) error if it is not related to username' , async ( ) => {
149+ const consoleErrorSpy = vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
150+
151+ const mongoError = new Error (
152+ 'E11000 duplicate key error collection: other_field'
153+ ) as Error & {
154+ code ?: number ;
155+ keyPattern ?: Record < string , number > ;
156+ } ;
157+ mongoError . code = 11000 ;
158+ mongoError . keyPattern = { other_field : 1 } ;
159+ vi . mocked ( User . updateOne ) . mockRejectedValueOnce ( mongoError ) ;
160+
161+ const response = await POST ( makeRequest ( { username : 'octocat' } ) ) ;
162+
163+ expect ( response . status ) . toBe ( 500 ) ;
164+ const data = await response . json ( ) ;
165+ expect ( data . success ) . toBe ( false ) ;
166+ expect ( data . error ) . toBe ( 'Internal server error' ) ;
167+ expect ( consoleErrorSpy ) . toHaveBeenCalled ( ) ;
168+
169+ consoleErrorSpy . mockRestore ( ) ;
170+ } ) ;
126171 } ) ;
127172} ) ;
0 commit comments