11import { containerTest } from "@internal/testcontainers" ;
2- import type { PrismaClient } from "@trigger.dev/database" ;
2+ import { boundedIn , type PrismaClient } from "@trigger.dev/database" ;
33import { describe , expect , vi } from "vitest" ;
44import { resolveProjectScopedEnvironments } from "~/v3/services/resolveProjectScopedEnvironments" ;
55
66vi . setConfig ( { testTimeout : 60_000 } ) ;
77
8- // Exercises the environment-scoping primitive CheckScheduleService relies on
9- // (`resolveProjectScopedEnvironments`) with real RuntimeEnvironment rows,
10- // imported directly to avoid `~/db.server` and its eager global-prisma connect.
11-
128async function seedProjectWithEnv ( prisma : PrismaClient , slugBase : string ) {
139 const slug = `${ slugBase } _${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) } ` ;
1410 const organization = await prisma . organization . create ( { data : { title : slug , slug } } ) ;
@@ -29,10 +25,47 @@ async function seedProjectWithEnv(prisma: PrismaClient, slugBase: string) {
2925 return { organization, project, environment } ;
3026}
3127
28+ async function seedBranchEnv (
29+ prisma : PrismaClient ,
30+ project : { id : string ; organizationId : string } ,
31+ slugBase : string ,
32+ { archived } : { archived : boolean }
33+ ) {
34+ const slug = `${ slugBase } _${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) } ` ;
35+ return prisma . runtimeEnvironment . create ( {
36+ data : {
37+ slug : `${ slug } -branch` ,
38+ type : "PREVIEW" ,
39+ branchName : slug ,
40+ projectId : project . id ,
41+ organizationId : project . organizationId ,
42+ apiKey : `tr_preview_${ slug } ` ,
43+ pkApiKey : `pk_preview_${ slug } ` ,
44+ shortcode : Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) ,
45+ archivedAt : archived ? new Date ( ) : null ,
46+ } ,
47+ } ) ;
48+ }
49+
3250function projectEnvironments ( prisma : PrismaClient , projectId : string ) {
3351 return prisma . runtimeEnvironment . findMany ( { where : { projectId } , select : { id : true } } ) ;
3452}
3553
54+ function loadScopedEnvironments ( prisma : PrismaClient , projectId : string , environmentIds : string [ ] ) {
55+ return prisma . project
56+ . findFirst ( {
57+ where : { id : projectId } ,
58+ select : {
59+ organizationId : true ,
60+ environments : {
61+ where : { id : { in : boundedIn ( environmentIds ) } } ,
62+ select : { id : true , type : true , archivedAt : true } ,
63+ } ,
64+ } ,
65+ } )
66+ . then ( ( project ) => project ?. environments ?? [ ] ) ;
67+ }
68+
3669describe ( "resolveProjectScopedEnvironments (schedule env scoping)" , ( ) => {
3770 containerTest ( "rejects an environment id that belongs to another project" , async ( { prisma } ) => {
3871 const a = await seedProjectWithEnv ( prisma , "orga" ) ;
@@ -58,3 +91,60 @@ describe("resolveProjectScopedEnvironments (schedule env scoping)", () => {
5891 expect ( result . kind ) . toBe ( "ok" ) ;
5992 } ) ;
6093} ) ;
94+
95+ describe ( "CheckScheduleService bounded environments load" , ( ) => {
96+ containerTest (
97+ "loads only the requested environments, not every project environment" ,
98+ async ( { prisma } ) => {
99+ const a = await seedProjectWithEnv ( prisma , "orga" ) ;
100+ for ( let i = 0 ; i < 8 ; i ++ ) {
101+ await seedBranchEnv ( prisma , a . project , `branch${ i } ` , { archived : true } ) ;
102+ }
103+ await seedBranchEnv ( prisma , a . project , "active" , { archived : false } ) ;
104+
105+ const all = await projectEnvironments ( prisma , a . project . id ) ;
106+ expect ( all . length ) . toBe ( 10 ) ;
107+
108+ const scoped = await loadScopedEnvironments ( prisma , a . project . id , [ a . environment . id ] ) ;
109+ expect ( scoped . length ) . toBe ( 1 ) ;
110+ expect ( scoped [ 0 ] ?. id ) . toBe ( a . environment . id ) ;
111+
112+ const result = resolveProjectScopedEnvironments ( [ a . environment . id ] , scoped ) ;
113+ expect ( result . kind ) . toBe ( "ok" ) ;
114+ }
115+ ) ;
116+
117+ containerTest (
118+ "still rejects a foreign environment id when the load is bounded" ,
119+ async ( { prisma } ) => {
120+ const a = await seedProjectWithEnv ( prisma , "orga" ) ;
121+ const b = await seedProjectWithEnv ( prisma , "orgb" ) ;
122+ await seedBranchEnv ( prisma , a . project , "branch" , { archived : true } ) ;
123+
124+ const scoped = await loadScopedEnvironments ( prisma , a . project . id , [
125+ a . environment . id ,
126+ b . environment . id ,
127+ ] ) ;
128+ expect ( scoped . length ) . toBe ( 1 ) ;
129+
130+ const result = resolveProjectScopedEnvironments ( [ a . environment . id , b . environment . id ] , scoped ) ;
131+ expect ( result . kind ) . toBe ( "foreign" ) ;
132+ expect ( result ) . toMatchObject ( { foreignEnvironmentId : b . environment . id } ) ;
133+ }
134+ ) ;
135+
136+ containerTest (
137+ "still surfaces an archived branch env when it is the requested one" ,
138+ async ( { prisma } ) => {
139+ const a = await seedProjectWithEnv ( prisma , "orga" ) ;
140+ const archivedBranch = await seedBranchEnv ( prisma , a . project , "branch" , { archived : true } ) ;
141+
142+ const scoped = await loadScopedEnvironments ( prisma , a . project . id , [ archivedBranch . id ] ) ;
143+ expect ( scoped . length ) . toBe ( 1 ) ;
144+
145+ const result = resolveProjectScopedEnvironments ( [ archivedBranch . id ] , scoped ) ;
146+ expect ( result . kind ) . toBe ( "ok" ) ;
147+ expect ( result . kind === "ok" && result . environments . some ( ( env ) => env . archivedAt ) ) . toBe ( true ) ;
148+ }
149+ ) ;
150+ } ) ;
0 commit comments