@@ -53,18 +53,40 @@ import { loader as projectsLoader } from "~/routes/api.v1.projects";
5353
5454const USER_ID = "usr_1" ;
5555
56- async function createOrg ( cap : string [ ] ) : Promise < { status : number ; body : any } > {
56+ // Counts `can()` invocations without changing what the ability answers.
57+ function countingAbility ( ability : any ) : { ability : any ; canCalls : ( ) => number } {
58+ let canCalls = 0 ;
59+ const wrapped = new Proxy ( ability , {
60+ get ( target , prop , receiver ) {
61+ const value = Reflect . get ( target , prop , receiver ) ;
62+ if ( typeof value !== "function" ) {
63+ return value ;
64+ }
65+ if ( prop === "can" ) {
66+ return ( ...args : any [ ] ) => {
67+ canCalls ++ ;
68+ return value . apply ( target , args ) ;
69+ } ;
70+ }
71+ return value . bind ( target ) ;
72+ } ,
73+ } ) ;
74+ return { ability : wrapped , canCalls : ( ) => canCalls } ;
75+ }
76+
77+ async function createOrg ( cap : string [ ] ) : Promise < { status : number ; body : any ; canCalls : number } > {
5778 const token = await signUserActorToken ( SESSION_SECRET , {
5879 userId : USER_ID ,
5980 client : "personal-access-token" ,
6081 cap,
6182 } ) ;
83+ const counted = countingAbility ( buildJwtAbility ( cap ) ) ;
6284 mocks . authenticateUserActor . mockImplementation ( async ( ) => ( {
6385 ok : true ,
6486 userId : USER_ID ,
6587 claims : { userId : USER_ID , client : "personal-access-token" , cap } ,
6688 subject : { type : "userActor" , userId : USER_ID , organizationId : "org_1" } ,
67- ability : buildJwtAbility ( cap ) ,
89+ ability : counted . ability ,
6890 } ) ) ;
6991
7092 const response = await action ( {
@@ -76,7 +98,7 @@ async function createOrg(cap: string[]): Promise<{ status: number; body: any }>
7698 params : { } ,
7799 context : { } ,
78100 } as any ) ;
79- return { status : response . status , body : await response . json ( ) } ;
101+ return { status : response . status , body : await response . json ( ) , canCalls : counted . canCalls ( ) } ;
80102}
81103
82104// An ordinary PAT, paired with an ability that denies everything. Nothing on this route may
@@ -197,6 +219,7 @@ describe("creating an organization over the API", () => {
197219 const result = await createOrg ( [ "read:all" ] ) ;
198220
199221 expect ( result . status ) . toBe ( 404 ) ;
222+ expect ( result . canCalls ) . toBe ( 0 ) ;
200223 expect ( mocks . createOrganization ) . not . toHaveBeenCalled ( ) ;
201224 } finally {
202225 mocks . env . ORG_CREATION_API_ENABLED = "1" ;
0 commit comments