@@ -5,8 +5,10 @@ import { createHmac } from 'crypto';
55vi . mock ( '@roo-code-cloud/db/server' , ( ) => ( {
66 db : {
77 insert : vi . fn ( ) ,
8+ select : vi . fn ( ) ,
89 } ,
910 cloudJobs : { } ,
11+ orgs : { } ,
1012} ) ) ;
1113
1214vi . mock ( '@/lib' , ( ) => ( {
@@ -17,17 +19,35 @@ describe('GitHub Webhook Utils', () => {
1719 let verifySignature : typeof import ( '../utils' ) . verifySignature ;
1820 let createAndEnqueueJob : typeof import ( '../utils' ) . createAndEnqueueJob ;
1921 let isRoomoteMention : typeof import ( '../utils' ) . isRoomoteMention ;
20- let mockDb : { insert : ReturnType < typeof vi . fn > } ;
22+ let mockDb : {
23+ insert : ReturnType < typeof vi . fn > ;
24+ select : ReturnType < typeof vi . fn > ;
25+ } ;
2126 let mockEnqueue : ReturnType < typeof vi . fn > ;
2227
2328 beforeEach ( async ( ) => {
2429 vi . clearAllMocks ( ) ;
2530
31+ // Set default environment variable for tests
32+ process . env . ROOMOTE_FALLBACK_USER_ID = 'test-user-123' ;
33+
2634 const dbModule = await import ( '@roo-code-cloud/db/server' ) ;
2735 const libModule = await import ( '@/lib' ) ;
28- mockDb = dbModule . db as unknown as { insert : ReturnType < typeof vi . fn > } ;
36+ mockDb = dbModule . db as unknown as {
37+ insert : ReturnType < typeof vi . fn > ;
38+ select : ReturnType < typeof vi . fn > ;
39+ } ;
2940 mockEnqueue = libModule . enqueue as unknown as ReturnType < typeof vi . fn > ;
3041
42+ // Mock the select chain for organization lookup
43+ mockDb . select . mockReturnValue ( {
44+ from : vi . fn ( ) . mockReturnValue ( {
45+ where : vi . fn ( ) . mockReturnValue ( {
46+ limit : vi . fn ( ) . mockResolvedValue ( [ { id : 'default-org-id' } ] ) ,
47+ } ) ,
48+ } ) ,
49+ } ) ;
50+
3151 const utilsModule = await import ( '../utils' ) ;
3252 verifySignature = utilsModule . verifySignature ;
3353 createAndEnqueueJob = utilsModule . createAndEnqueueJob ;
@@ -205,7 +225,7 @@ describe('GitHub Webhook Utils', () => {
205225 } ) ;
206226 } ) ;
207227
208- it ( 'should log the enqueued job' , async ( ) => {
228+ it ( 'should log the enqueued job with user ID ' , async ( ) => {
209229 const consoleSpy = vi . spyOn ( console , 'log' ) . mockImplementation ( ( ) => { } ) ;
210230
211231 const type = 'github.issue.fix' ;
@@ -259,6 +279,57 @@ describe('GitHub Webhook Utils', () => {
259279 createAndEnqueueJob ( type , payload , testOrgId ) ,
260280 ) . rejects . toThrow ( 'Queue service unavailable' ) ;
261281 } ) ;
282+
283+ it ( 'should always include fallback user ID in job creation' , async ( ) => {
284+ const type = 'github.issue.fix' ;
285+ const payload = {
286+ repo : 'test/repo' ,
287+ issue : 123 ,
288+ title : 'Test issue' ,
289+ body : 'Test body' ,
290+ } ;
291+
292+ const mockValuesCall = vi . fn ( ) . mockReturnValue ( {
293+ returning : vi . fn ( ) . mockResolvedValue ( [ mockJob ] ) ,
294+ } ) ;
295+ mockDb . insert . mockReturnValue ( {
296+ values : mockValuesCall ,
297+ } ) ;
298+
299+ await createAndEnqueueJob ( type , payload , testOrgId ) ;
300+
301+ expect ( mockValuesCall ) . toHaveBeenCalledWith ( {
302+ type,
303+ payload,
304+ status : 'pending' ,
305+ orgId : testOrgId ,
306+ userId : 'test-user-123' ,
307+ } ) ;
308+ } ) ;
309+
310+ it ( 'should throw error when ROOMOTE_FALLBACK_USER_ID is not set' , async ( ) => {
311+ const originalEnv = process . env . ROOMOTE_FALLBACK_USER_ID ;
312+ delete process . env . ROOMOTE_FALLBACK_USER_ID ;
313+
314+ const type = 'github.issue.fix' ;
315+ const payload = {
316+ repo : 'test/repo' ,
317+ issue : 123 ,
318+ title : 'Test issue' ,
319+ body : 'Test body' ,
320+ } ;
321+
322+ await expect (
323+ createAndEnqueueJob ( type , payload , testOrgId ) ,
324+ ) . rejects . toThrow (
325+ 'ROOMOTE_FALLBACK_USER_ID environment variable is required but not set' ,
326+ ) ;
327+
328+ // Restore original environment
329+ if ( originalEnv !== undefined ) {
330+ process . env . ROOMOTE_FALLBACK_USER_ID = originalEnv ;
331+ }
332+ } ) ;
262333 } ) ;
263334
264335 describe ( 'isRoomoteMention' , ( ) => {
0 commit comments