@@ -16,9 +16,12 @@ import { createSelectorProtectedValues } from '@/lib/selectors/server/protected-
1616import { hubspotSelectorAttachments } from '@/lib/selectors/server/providers/hubspot'
1717import type { ExecuteServerSelectorArgs } from '@/lib/selectors/server/types'
1818
19- function args ( request : ExecuteServerSelectorArgs [ 'request' ] ) : ExecuteServerSelectorArgs {
19+ function args (
20+ request : ExecuteServerSelectorArgs [ 'request' ] ,
21+ selectorKey : ExecuteServerSelectorArgs [ 'selectorKey' ] = 'hubspot.lists'
22+ ) : ExecuteServerSelectorArgs {
2023 return {
21- selectorKey : 'hubspot.lists' ,
24+ selectorKey,
2225 context : { oauthCredential : 'credential-1' } ,
2326 request,
2427 scope : { kind : 'workspace' , workspaceId : 'workspace-1' } ,
@@ -113,4 +116,67 @@ describe('HubSpot server selector adapter', () => {
113116 expect ( String ( mockFetch . mock . calls [ 0 ] ?. [ 0 ] ) ) . toBe ( 'https://api.hubapi.com/crm/v3/lists/123' )
114117 expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 )
115118 } )
119+
120+ it ( 'paginates active owners through the HubSpot continuation cursor on demand' , async ( ) => {
121+ mockFetch
122+ . mockResolvedValueOnce (
123+ new Response (
124+ JSON . stringify ( {
125+ results : [
126+ { id : '100' , firstName : 'Former' , lastName : 'Owner' , archived : true } ,
127+ { id : '101' , firstName : 'Ada' , lastName : 'Lovelace' , archived : false } ,
128+ ] ,
129+ paging : { next : { after : 'owner-page-2' } } ,
130+ } ) ,
131+ { status : 200 }
132+ )
133+ )
134+ . mockResolvedValueOnce (
135+ new Response ( JSON . stringify ( { results : [ { id : '102' , email : 'grace@example.com' } ] } ) , {
136+ status : 200 ,
137+ } )
138+ )
139+
140+ const first = await hubspotSelectorAttachments [ 'hubspot.owners' ] . execute (
141+ args ( { kind : 'list' } , 'hubspot.owners' )
142+ )
143+ const second = await hubspotSelectorAttachments [ 'hubspot.owners' ] . execute (
144+ args ( { kind : 'list' , cursor : 'owner-page-2' } , 'hubspot.owners' )
145+ )
146+
147+ expect ( first ) . toEqual ( {
148+ kind : 'list' ,
149+ items : [ { id : '101' , label : 'Ada Lovelace' } ] ,
150+ nextCursor : 'owner-page-2' ,
151+ } )
152+ expect ( second ) . toEqual ( {
153+ kind : 'list' ,
154+ items : [ { id : '102' , label : 'grace@example.com' } ] ,
155+ } )
156+ const firstUrl = new URL ( String ( mockFetch . mock . calls [ 0 ] ?. [ 0 ] ) )
157+ const secondUrl = new URL ( String ( mockFetch . mock . calls [ 1 ] ?. [ 0 ] ) )
158+ expect ( firstUrl . searchParams . get ( 'limit' ) ) . toBe ( '100' )
159+ expect ( firstUrl . searchParams . has ( 'after' ) ) . toBe ( false )
160+ expect ( secondUrl . searchParams . get ( 'after' ) ) . toBe ( 'owner-page-2' )
161+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 2 )
162+ } )
163+
164+ it ( 'hydrates a selected owner directly by id' , async ( ) => {
165+ mockFetch . mockResolvedValueOnce (
166+ new Response ( JSON . stringify ( { id : '777' , firstName : 'Katherine' , lastName : 'Johnson' } ) , {
167+ status : 200 ,
168+ } )
169+ )
170+
171+ await expect (
172+ hubspotSelectorAttachments [ 'hubspot.owners' ] . execute (
173+ args ( { kind : 'detail' , id : '777' } , 'hubspot.owners' )
174+ )
175+ ) . resolves . toEqual ( {
176+ kind : 'detail' ,
177+ item : { id : '777' , label : 'Katherine Johnson' } ,
178+ } )
179+ expect ( String ( mockFetch . mock . calls [ 0 ] ?. [ 0 ] ) ) . toBe ( 'https://api.hubapi.com/crm/v3/owners/777' )
180+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 )
181+ } )
116182} )
0 commit comments