11/** @vitest -environment node */
22
3- import { databaseMock , dbChainMock , dbChainMockFns , resetDbChainMock } from '@sim/testing '
4- import type { Mock } from 'vitest '
3+ import { member , organization , permissions , subscription } from '@sim/db/schema '
4+ import { dbChainMock , dbChainMockFns , queueTableRows , resetDbChainMock } from '@sim/testing '
55import { afterAll , beforeEach , describe , expect , it , vi } from 'vitest'
66
77vi . unmock ( 'drizzle-orm' )
88
99const mocks = vi . hoisted ( ( ) => ( {
10- queryRows : [ ] as unknown [ ] [ ] ,
11- selectCalls : 0 ,
12- selectDistinctOnCalls : 0 ,
1310 provisionings : new Map ( ) ,
1411} ) )
1512
@@ -65,78 +62,8 @@ vi.mock('@/lib/core/outbox/service', () => ({ enqueueOutboxEvent: vi.fn() }))
6562
6663import { listDashboardOrganizations , toDashboardConfigurationUpdate } from '@/lib/admin/dashboard'
6764
68- /**
69- * `@sim/db` behavior is driven through the SHARED `dbChainMockFns` instances
70- * instead of a file-local factory object. This file mocks `@sim/db` with
71- * `dbChainMock` and installs the queued-rows select implementation in
72- * `beforeEach`; the setup-level `databaseMock` entry points are mirrored onto
73- * the same chain fns. Under `isolate: false` the module under test may have
74- * been loaded by an earlier suite in this worker with `@sim/db` bound to
75- * `databaseMock` — configuring both shared instances keeps either binding
76- * correct.
77- */
78- function queryChain ( rows : unknown [ ] ) {
79- const chain : Record < string , unknown > = { }
80- for ( const method of [ 'from' , 'innerJoin' , 'leftJoin' , 'where' , 'orderBy' , 'limit' ] ) {
81- chain [ method ] = ( ) => chain
82- }
83- chain . offset = ( ) => Promise . resolve ( rows )
84- chain . groupBy = ( ) => Promise . resolve ( rows )
85- chain . then = ( resolve : ( value : unknown [ ] ) => unknown , reject : ( error : unknown ) => unknown ) =>
86- Promise . resolve ( rows ) . then ( resolve , reject )
87- return chain
88- }
89-
90- function queuedSelect ( ) {
91- const rows = mocks . queryRows [ mocks . selectCalls ] ?? [ ]
92- mocks . selectCalls += 1
93- return queryChain ( rows )
94- }
95-
96- function queuedSelectDistinctOn ( ) {
97- const rows = mocks . queryRows [ mocks . selectCalls ] ?? [ ]
98- mocks . selectCalls += 1
99- mocks . selectDistinctOnCalls += 1
100- return queryChain ( rows )
101- }
102-
103- const GLOBAL_DB_KEYS = [
104- 'select' ,
105- 'selectDistinct' ,
106- 'selectDistinctOn' ,
107- 'insert' ,
108- 'update' ,
109- 'delete' ,
110- 'transaction' ,
111- ] as const
112-
113- const globalDb = databaseMock . db as unknown as Record < ( typeof GLOBAL_DB_KEYS ) [ number ] , Mock >
114- const savedGlobalDbImpls = new Map <
115- ( typeof GLOBAL_DB_KEYS ) [ number ] ,
116- ( ( ...args : unknown [ ] ) => unknown ) | undefined
117- > ( )
118-
119- /** Mirrors the setup-level databaseMock entry points onto the shared chain fns. */
120- function delegateGlobalDbToChainMocks ( ) : void {
121- for ( const key of GLOBAL_DB_KEYS ) {
122- const fn = globalDb [ key ]
123- if ( typeof fn ?. mockImplementation !== 'function' ) continue
124- if ( ! savedGlobalDbImpls . has ( key ) ) savedGlobalDbImpls . set ( key , fn . getMockImplementation ( ) )
125- fn . mockImplementation ( ( ...args : unknown [ ] ) => ( dbChainMockFns [ key ] as Mock ) ( ...args ) )
126- }
127- }
128-
129- /** Restores the databaseMock entry points captured before this suite ran. */
130- function restoreGlobalDb ( ) : void {
131- for ( const [ key , impl ] of savedGlobalDbImpls ) {
132- if ( impl ) globalDb [ key ] . mockImplementation ( impl )
133- else globalDb [ key ] . mockReset ( )
134- }
135- }
136-
13765afterAll ( ( ) => {
13866 resetDbChainMock ( )
139- restoreGlobalDb ( )
14067} )
14168
14269describe ( 'toDashboardConfigurationUpdate' , ( ) => {
@@ -173,48 +100,41 @@ describe('listDashboardOrganizations', () => {
173100 beforeEach ( ( ) => {
174101 vi . clearAllMocks ( )
175102 resetDbChainMock ( )
176- dbChainMockFns . select . mockImplementation ( queuedSelect )
177- dbChainMockFns . selectDistinctOn . mockImplementation ( queuedSelectDistinctOn )
178- delegateGlobalDbToChainMocks ( )
179- mocks . selectCalls = 0
180- mocks . selectDistinctOnCalls = 0
181103 mocks . provisionings = new Map ( )
182104 } )
183105
184106 it ( 'loads a page with a fixed batch of queries instead of querying once per organization' , async ( ) => {
185- mocks . queryRows = [
186- [ { total : 2 } ] ,
187- [
188- { id : 'org-1' , name : 'One' , orgUsageLimit : '10' , creditBalance : '1' } ,
189- { id : 'org-2' , name : 'Two' , orgUsageLimit : '20' , creditBalance : '2' } ,
190- ] ,
191- [
192- {
193- organizationId : 'org-1' ,
194- memberCount : 2 ,
195- ownerId : 'owner-1' ,
196- ownerName : 'Owner One' ,
197- ownerEmail : 'one@example.com' ,
198- } ,
199- {
200- organizationId : 'org-2' ,
201- memberCount : 1 ,
202- ownerId : 'owner-2' ,
203- ownerName : 'Owner Two' ,
204- ownerEmail : 'two@example.com' ,
205- } ,
206- ] ,
207- [ { organizationId : 'org-1' , externalCollaboratorCount : 3 } ] ,
208- [
209- {
210- id : 'sub-1' ,
211- referenceId : 'org-1' ,
212- plan : 'team_6000' ,
213- status : 'active' ,
214- metadata : null ,
215- } ,
216- ] ,
217- ]
107+ queueTableRows ( organization , [ { total : 2 } ] )
108+ queueTableRows ( organization , [
109+ { id : 'org-1' , name : 'One' , orgUsageLimit : '10' , creditBalance : '1' } ,
110+ { id : 'org-2' , name : 'Two' , orgUsageLimit : '20' , creditBalance : '2' } ,
111+ ] )
112+ queueTableRows ( member , [
113+ {
114+ organizationId : 'org-1' ,
115+ memberCount : 2 ,
116+ ownerId : 'owner-1' ,
117+ ownerName : 'Owner One' ,
118+ ownerEmail : 'one@example.com' ,
119+ } ,
120+ {
121+ organizationId : 'org-2' ,
122+ memberCount : 1 ,
123+ ownerId : 'owner-2' ,
124+ ownerName : 'Owner Two' ,
125+ ownerEmail : 'two@example.com' ,
126+ } ,
127+ ] )
128+ queueTableRows ( permissions , [ { organizationId : 'org-1' , externalCollaboratorCount : 3 } ] )
129+ queueTableRows ( subscription , [
130+ {
131+ id : 'sub-1' ,
132+ referenceId : 'org-1' ,
133+ plan : 'team_6000' ,
134+ status : 'active' ,
135+ metadata : null ,
136+ } ,
137+ ] )
218138
219139 const result = await listDashboardOrganizations ( { search : '' , limit : 50 , offset : 0 } )
220140
@@ -231,7 +151,7 @@ describe('listDashboardOrganizations', () => {
231151 externalCollaboratorCount : 0 ,
232152 planLabel : 'No plan' ,
233153 } )
234- expect ( mocks . selectCalls ) . toBe ( 5 )
235- expect ( mocks . selectDistinctOnCalls ) . toBe ( 1 )
154+ expect ( dbChainMockFns . select ) . toHaveBeenCalledTimes ( 4 )
155+ expect ( dbChainMockFns . selectDistinctOn ) . toHaveBeenCalledTimes ( 1 )
236156 } )
237157} )
0 commit comments