@@ -15,17 +15,42 @@ import {
1515 makeDeleteRequest ,
1616 checkRecordInStaging ,
1717} from './helpers/api-request-helpers.js' ;
18- import { addCreatedId , shouldAutoCommit , trackBatchVerification , getFirstRecordIdFromDatabase , getAllRecordIdsFromDatabase } from './helpers/shared-state.js' ;
18+ import { addCreatedId , getCreatedIds , shouldAutoCommit , trackBatchVerification , getFirstRecordIdFromDatabase , getAllRecordIdsFromDatabase } from './helpers/shared-state.js' ;
1919import {
2020 generateProgram ,
2121 generateProgramMinimal ,
2222 generateProgramMaximal ,
2323 generateProgramLongStrings ,
2424 generateProgramForbiddenFields ,
25- getLongString ,
26- getInvalidPicklistValue ,
2725} from './data/test-data-generators.js' ;
2826
27+ const REFERENCE_ERROR_CODE = 'Referenced records must be removed before deletion' ;
28+ const deleteTargetProgramIds = new Set ( ) ;
29+ const blockedProgramIds = new Set ( ) ;
30+
31+ const getReferencedProgramIds = async ( request ) => {
32+ const referencedProgramIds = new Set ( ) ;
33+ let page = 1 ;
34+ const limit = 1000 ;
35+ let hasMore = true ;
36+
37+ while ( hasMore ) {
38+ const response = await request . get ( '/v2/project' ) . query ( { page, limit } ) . expect ( 200 ) ;
39+ const data = Array . isArray ( response . body ) ? response . body : ( response . body ?. data || [ ] ) ;
40+ for ( const project of data ) {
41+ if ( project . cadTrustProgramId ) {
42+ referencedProgramIds . add ( project . cadTrustProgramId ) ;
43+ }
44+ }
45+
46+ const totalPages = response . body ?. pageCount || 1 ;
47+ hasMore = page < totalPages && data . length === limit ;
48+ page ++ ;
49+ }
50+
51+ return referencedProgramIds ;
52+ } ;
53+
2954describe ( 'Program Live API Validation Tests' , function ( ) {
3055 this . timeout ( 600000 ) ; // 10 minute timeout
3156 let request ;
@@ -261,9 +286,9 @@ describe('Program Live API Validation Tests', function () {
261286 } ) ;
262287 } ) ;
263288 describe ( 'Step 9: DELETE Request Tests' , function ( ) {
264- it ( 'should delete all created programs' , async function ( ) {
289+ it ( 'should delete unreferenced programs and preserve referenced programs' , async function ( ) {
265290 // Get IDs from createdIds (if available) or query database for existing records
266- let idsToDelete = createdIds . length > 0 ? createdIds : [ ] ;
291+ let idsToDelete = createdIds . length > 0 ? createdIds : getCreatedIds ( 'program' ) ;
267292 if ( idsToDelete . length === 0 ) {
268293 // Query database to get all existing records (for DELETE tests running in separate process)
269294 idsToDelete = await getAllRecordIdsFromDatabase ( request , 'program' ) ;
@@ -273,11 +298,18 @@ describe('Program Live API Validation Tests', function () {
273298 // No records to delete, skip test
274299 return ;
275300 }
301+ idsToDelete . forEach ( ( id ) => deleteTargetProgramIds . add ( id ) ) ;
276302
277303 // Delete in reverse order
278304 for ( let i = idsToDelete . length - 1 ; i >= 0 ; i -- ) {
279305 const id = idsToDelete [ i ] ;
280306 const response = await makeDeleteRequest ( request , '/v2/program' , id ) ;
307+ if ( response . success === false && response . error === REFERENCE_ERROR_CODE ) {
308+ expect ( response . references ) . to . be . an ( 'array' ) . that . is . not . empty ;
309+ expect ( response . references . some ( ( ref ) => ref . table === 'project' && ref . count > 0 ) ) . to . be . true ;
310+ blockedProgramIds . add ( id ) ;
311+ continue ;
312+ }
281313 expect ( response . success ) . to . be . true ;
282314
283315 if ( shouldAutoCommit ( ) ) {
@@ -293,11 +325,24 @@ describe('Program Live API Validation Tests', function () {
293325 } ) ;
294326
295327 describe ( 'Step 10: Final Validation' , function ( ) {
296- it ( 'should verify all programs are deleted' , async function ( ) {
297- const response = await request . get ( '/v2/program' ) . query ( { page : 1 , limit : 10 } ) . expect ( 200 ) ;
298- const data = Array . isArray ( response . body ) ? response . body : ( response . body ?. data || [ ] ) ;
299- // Should only have programs that existed before tests
300- expect ( data . length ) . to . equal ( 0 ) ;
328+ it ( 'should verify remaining created programs are still referenced' , async function ( ) {
329+ let idsToCheck = createdIds . length > 0 ? createdIds : getCreatedIds ( 'program' ) ;
330+ if ( idsToCheck . length === 0 ) {
331+ idsToCheck = [ ...deleteTargetProgramIds ] ;
332+ }
333+ const referencedProgramIds = await getReferencedProgramIds ( request ) ;
334+
335+ for ( const id of idsToCheck ) {
336+ const response = await request . get ( `/v2/program/${ id } ` ) ;
337+ if ( response . status === 404 ) {
338+ continue ;
339+ }
340+ expect ( response . status ) . to . equal ( 200 ) ;
341+ expect (
342+ referencedProgramIds . has ( id ) || blockedProgramIds . has ( id ) ,
343+ `Program ${ id } remains without committed or delete-time project references` ,
344+ ) . to . be . true ;
345+ }
301346 } ) ;
302347 } ) ;
303348} ) ;
0 commit comments