@@ -858,23 +858,38 @@ describe('layout.js', () => {
858858 } ) ;
859859
860860 describe ( 'cache edge cases' , ( ) => {
861- test ( 'should skip cache when lockfile indicates file is locked' , ( done ) => {
862- const content = '<% block test %>Lock Cache Test<% /block %>' ;
863- fs . writeFileSync ( path . join ( testDir , 'locked-cache.html' ) , content ) ;
864861
865- // Mock lockfile.isLocked to always return true (locked)
866- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
867- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
868- callback ( true ) ; // Always locked
869- } ;
862+ test ( 'should handle locked cache files during cache retrieval' , ( done ) => {
863+ const content = '<% block test %>Cache Lock Test<% /block %>' ;
864+ fs . writeFileSync ( path . join ( testDir , 'cache-lock.html' ) , content ) ;
870865
871- layout . make ( 'locked-cache.html' , { cache : true } , ( err , content ) => {
872- expect ( err ) . toBeNull ( ) ;
873- expect ( content ) . toContain ( 'Lock Cache Test' ) ;
866+ // Create cache first
867+ layout . make ( 'cache-lock.html' , { cache : true } , ( err1 ) => {
868+ expect ( err1 ) . toBeNull ( ) ;
874869
875- // Restore original function
876- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
877- done ( ) ;
870+ // Now mock the isLocked function to simulate cache lock
871+ const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
872+ require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
873+ // Return true for cache files (triggers line 469)
874+ callback ( true ) ;
875+ } ;
876+
877+ // Also mock fileExists to ensure cache file exists check passes
878+ const originalFileExists = require ( '../lib/utils' ) . fileExists ;
879+ require ( '../lib/utils' ) . fileExists = ( filePath , callback ) => {
880+ callback ( true ) ; // Cache file exists
881+ } ;
882+
883+ // This should trigger the cache lock path (line 469)
884+ layout . make ( 'cache-lock.html' , { cache : true } , ( err2 , content2 ) => {
885+ expect ( err2 ) . toBeNull ( ) ;
886+ expect ( content2 ) . toContain ( 'Cache Lock Test' ) ;
887+
888+ // Restore original functions
889+ require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
890+ require ( '../lib/utils' ) . fileExists = originalFileExists ;
891+ done ( ) ;
892+ } ) ;
878893 } ) ;
879894 } ) ;
880895
@@ -897,6 +912,31 @@ describe('layout.js', () => {
897912 } ) ;
898913
899914 describe ( 'comprehensive edge cases' , ( ) => {
915+ test ( 'should handle block hide mode specifically' , ( done ) => {
916+ const parentContent = `
917+ <% block content %>
918+ <% block visible %>Visible Content<% /block %>
919+ <% block hidden hide %>Hidden Content<% /block %>
920+ <% /block %>
921+ ` ;
922+ fs . writeFileSync ( path . join ( testDir , 'parent.html' ) , parentContent ) ;
923+
924+ const childContent = `<% extends parent %>
925+ <% block content %>
926+ <% block visible %>Child Visible<% /block %>
927+ <% block hidden hide %>Child Hidden<% /block %>
928+ <% /block %>` ;
929+ fs . writeFileSync ( path . join ( testDir , 'hide-mode.html' ) , childContent ) ;
930+
931+ layout . make ( 'hide-mode.html' , { cache : false } , ( err , content ) => {
932+ expect ( err ) . toBeNull ( ) ;
933+ expect ( content ) . toContain ( 'Child Visible' ) ;
934+ expect ( content ) . not . toContain ( 'Hidden Content' ) ;
935+ expect ( content ) . not . toContain ( 'Child Hidden' ) ;
936+ done ( ) ;
937+ } ) ;
938+ } ) ;
939+
900940 test ( 'should handle multiple file inheritance with successful cache hit' , ( done ) => {
901941 // Create a chain of files to trigger multiple file time checks
902942 const grandparentContent = '<% block content %>Grandparent<% /block %>' ;
@@ -967,20 +1007,6 @@ describe('layout.js', () => {
9671007 } ) ;
9681008 } ) ;
9691009
970- test ( 'should handle block hide mode specifically' , ( done ) => {
971- const content = `
972- <% block visible %>Visible Content<% /block %>
973- <% block hidden hide %>Hidden Content<% /block %>
974- ` ;
975- fs . writeFileSync ( path . join ( testDir , 'hide-mode.html' ) , content ) ;
976-
977- layout . make ( 'hide-mode.html' , { cache : false } , ( err , content ) => {
978- expect ( err ) . toBeNull ( ) ;
979- expect ( content ) . toContain ( 'Visible Content' ) ;
980- expect ( content ) . not . toContain ( 'Hidden Content' ) ;
981- done ( ) ;
982- } ) ;
983- } ) ;
9841010
9851011 test ( 'should match use command parameters to slot names correctly' , ( done ) => {
9861012 const content = `
@@ -1055,93 +1081,9 @@ describe('layout.js', () => {
10551081 } ) ;
10561082 } ) ;
10571083
1058- test ( 'should skip compilation when cache file is locked' , ( done ) => {
1059- const content = '<% block test %>Locked Cache Test<% /block %>' ;
1060- fs . writeFileSync ( path . join ( testDir , 'locked-exact.html' ) , content ) ;
1061-
1062- // Mock isLocked to return true
1063- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
1064- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
1065- callback ( true ) ; // File is locked
1066- } ;
1067-
1068- layout . make ( 'locked-exact.html' , { cache : true } , ( err , content ) => {
1069- expect ( err ) . toBeNull ( ) ;
1070- expect ( content ) . toContain ( 'Locked Cache Test' ) ;
1071-
1072- // Restore original
1073- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
1074- done ( ) ;
1075- } ) ;
1076- } ) ;
1077-
1078- test ( 'should hide blocks marked with hide mode' , ( done ) => {
1079- const parentContent = `
1080- <% block sidebar %>Sidebar<% /block %>
1081- <% block hidden hide %>This will be hidden<% /block %>
1082- ` ;
1083- fs . writeFileSync ( path . join ( testDir , 'parent.html' ) , parentContent ) ;
1084-
1085- const childContent = `<% extends parent %>
1086- <% block sidebar %>Child Sidebar<% /block %>
1087- <% block hidden hide %>Child Hidden<% /block %>` ;
1088- fs . writeFileSync ( path . join ( testDir , 'hide-exact.html' ) , childContent ) ;
1089-
1090- layout . make ( 'hide-exact.html' , { cache : false } , ( err , content ) => {
1091- expect ( err ) . toBeNull ( ) ;
1092- expect ( content ) . toContain ( 'Child Sidebar' ) ;
1093- expect ( content ) . not . toContain ( 'Child Hidden' ) ;
1094- expect ( content ) . not . toContain ( 'This will be hidden' ) ;
1095- done ( ) ;
1096- } ) ;
1097- } ) ;
1098-
1099- test ( 'should replace slot content using use command parameters' , ( done ) => {
1100- const content = `
1101- <% block reusable %>
1102- <h1><% slot title %>Default Title<% /slot %></h1>
1103- <p><% slot content %>Default Content<% /slot %></p>
1104- <% /block %>
1105-
1106- <% block main %>
1107- <% use reusable title="Used Title" content="Used Content" %>
1108- <% /block %>
1109- ` ;
1110- fs . writeFileSync ( path . join ( testDir , 'use-exact.html' ) , content ) ;
1111-
1112- layout . make ( 'use-exact.html' , { cache : false , block : 'main' } , ( err , content ) => {
1113- expect ( err ) . toBeNull ( ) ;
1114- expect ( content ) . toContain ( 'Used Title' ) ;
1115- expect ( content ) . toContain ( 'Used Content' ) ;
1116- done ( ) ;
1117- } ) ;
1118- } ) ;
11191084
1120- test ( 'should handle slot replacement in call command' , ( done ) => {
1121- const content = `
1122- <% block template %>
1123- <section>
1124- <% slot header %>Default Header<% /slot %>
1125- <% slot %>Default Body<% /slot %>
1126- </section>
1127- <% /block %>
11281085
1129- <% block main %>
1130- <% call template header="Called Header" %>
1131- <% slot body %>Called Body<% /slot %>
1132- <% slot %>Called Default Slot<% /slot %>
1133- <% /call %>
1134- <% /block %>
1135- ` ;
1136- fs . writeFileSync ( path . join ( testDir , 'call-exact.html' ) , content ) ;
11371086
1138- layout . make ( 'call-exact.html' , { cache : false , block : 'main' } , ( err , content ) => {
1139- expect ( err ) . toBeNull ( ) ;
1140- expect ( content ) . toContain ( 'Called Header' ) ;
1141- expect ( content ) . toContain ( 'Called Default Slot' ) ;
1142- done ( ) ;
1143- } ) ;
1144- } ) ;
11451087
11461088 test ( 'should handle unnamed slots in call command' , ( done ) => {
11471089 const content = `
@@ -1217,25 +1159,6 @@ describe('layout.js', () => {
12171159 } ) ;
12181160 } ) ;
12191161
1220- test ( 'should handle locked cache files during template compilation' , ( done ) => {
1221- const content = '<% block test %>Cache Lock Test<% /block %>' ;
1222- fs . writeFileSync ( path . join ( testDir , 'cache-lock-469.html' ) , content ) ;
1223-
1224- // Mock lockfile.isLocked to simulate locked state exactly
1225- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
1226- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
1227- callback ( true ) ; // Return locked=true to handle locked cache file
1228- } ;
1229-
1230- layout . make ( 'cache-lock-469.html' , { cache : true } , ( err , content ) => {
1231- expect ( err ) . toBeNull ( ) ;
1232- expect ( content ) . toContain ( 'Cache Lock Test' ) ;
1233-
1234- // Restore original
1235- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
1236- done ( ) ;
1237- } ) ;
1238- } ) ;
12391162
12401163 test ( 'unnamed slot in call command' , ( done ) => {
12411164 const content = `
@@ -1261,57 +1184,7 @@ describe('layout.js', () => {
12611184 } ) ;
12621185 } ) ;
12631186
1264- test ( 'should process use command with parameter substitution' , ( done ) => {
1265- const content = `
1266- <% block template %>
1267- <div class="widget">
1268- <h3><% slot title %>Default Title<% /slot %></h3>
1269- <div><% slot content %>Default Content<% /slot %></div>
1270- </div>
1271- <% /block %>
1272-
1273- <% block main %>
1274- <% use template title="My Title" content="My Content" %>
1275- <% /block %>
1276- ` ;
1277- fs . writeFileSync ( path . join ( testDir , 'use-direct.html' ) , content ) ;
1278-
1279- layout . make ( 'use-direct.html' , { cache : false , block : 'main' } , ( err , content ) => {
1280- expect ( err ) . toBeNull ( ) ;
1281- expect ( content ) . toContain ( 'My Title' ) ;
1282- expect ( content ) . toContain ( 'My Content' ) ;
1283- done ( ) ;
1284- } ) ;
1285- } ) ;
1286-
1287- test ( 'should process call command with slot content substitution' , ( done ) => {
1288- const content = `
1289- <% block template %>
1290- <article>
1291- <h1><% slot title %>Default Title<% /slot %></h1>
1292- <p><% slot content %>Default Content<% /slot %></p>
1293- <footer><% slot %>Default Footer<% /slot %></footer>
1294- </article>
1295- <% /block %>
1296-
1297- <% block main %>
1298- <% call template title="Call Title" content="Call Content" %>
1299- <% slot footer %>Call Footer<% /slot %>
1300- <% slot %>Call Default<% /slot %>
1301- <% /call %>
1302- <% /block %>
1303- ` ;
1304- fs . writeFileSync ( path . join ( testDir , 'call-direct.html' ) , content ) ;
13051187
1306- layout . make ( 'call-direct.html' , { cache : false , block : 'main' } , ( err , content ) => {
1307- expect ( err ) . toBeNull ( ) ;
1308- expect ( content ) . toContain ( 'Call Title' ) ;
1309- expect ( content ) . toContain ( 'Call Content' ) ;
1310- expect ( content ) . toContain ( 'Call Footer' ) ;
1311- expect ( content ) . toContain ( 'Call Default' ) ;
1312- done ( ) ;
1313- } ) ;
1314- } ) ;
13151188
13161189 test ( 'should parse use command parameters in template inheritance' , ( done ) => {
13171190 const parentContent = `
@@ -1378,40 +1251,6 @@ describe('layout.js', () => {
13781251 } ) ;
13791252 } ) ;
13801253
1381- test ( 'should handle cache lock state changes during compilation' , ( done ) => {
1382- const content = '<% block test %>Lock Test 469<% /block %>' ;
1383- fs . writeFileSync ( path . join ( testDir , 'lock-469.html' ) , content ) ;
1384-
1385- // Mock lockfile.isLocked to return true immediately
1386- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
1387- let callCount = 0 ;
1388- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
1389- callCount ++ ;
1390- if ( callCount === 1 ) {
1391- // First call: not locked, to create cache
1392- callback ( false ) ;
1393- }
1394- else {
1395- // Second call: locked, to handle cache lock
1396- callback ( true ) ;
1397- }
1398- } ;
1399-
1400- // First call to create cache
1401- layout . make ( 'lock-469.html' , { cache : true } , ( err1 ) => {
1402- expect ( err1 ) . toBeNull ( ) ;
1403-
1404- // Second call should handle cache lock
1405- layout . make ( 'lock-469.html' , { cache : true } , ( err2 , content2 ) => {
1406- expect ( err2 ) . toBeNull ( ) ;
1407- expect ( content2 ) . toContain ( 'Lock Test 469' ) ;
1408-
1409- // Restore original
1410- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
1411- done ( ) ;
1412- } ) ;
1413- } ) ;
1414- } ) ;
14151254
14161255 test ( 'should handle use command referencing non-existent blocks' , ( done ) => {
14171256 // Create a scenario where use references a block that doesn't exist anywhere
@@ -1461,55 +1300,7 @@ describe('layout.js', () => {
14611300 } ) ;
14621301 } ) ;
14631302
1464- test ( 'should handle immediate cache lock during cache retrieval' , ( done ) => {
1465- // Direct test to handle cache lock in getCache method
1466- const content = '<% block test %>Direct Lock Test<% /block %>' ;
1467- fs . writeFileSync ( path . join ( testDir , 'direct-lock.html' ) , content ) ;
1468-
1469- // Mock lockfile.isLocked to always return true (locked)
1470- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
1471- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
1472- // Always return locked = true to handle cache lock
1473- callback ( true ) ;
1474- } ;
1475-
1476- layout . make ( 'direct-lock.html' , { cache : true } , ( err , content ) => {
1477- expect ( err ) . toBeNull ( ) ;
1478- expect ( content ) . toContain ( 'Direct Lock Test' ) ;
1479-
1480- // Restore original
1481- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
1482- done ( ) ;
1483- } ) ;
1484- } ) ;
1485-
1486- test ( 'should handle cache lock when cache file exists' , ( done ) => {
1487- const content = '<% block test %>Cache Lock Line 469<% /block %>' ;
1488- const fileName = 'cache-469-test.html' ;
1489- fs . writeFileSync ( path . join ( testDir , fileName ) , content ) ;
1490-
1491- // Mock fileExists to return true, then isLocked to return true
1492- const originalFileExists = require ( '../lib/utils' ) . fileExists ;
1493- const originalIsLocked = require ( '../lib/lockfile' ) . isLocked ;
1494-
1495- require ( '../lib/utils' ) . fileExists = ( filename , callback ) => {
1496- callback ( true ) ; // Cache file exists
1497- } ;
14981303
1499- require ( '../lib/lockfile' ) . isLocked = ( filePath , callback ) => {
1500- callback ( true ) ; // File is locked - should handle cache lock
1501- } ;
1502-
1503- layout . make ( fileName , { cache : true } , ( err , content ) => {
1504- expect ( err ) . toBeNull ( ) ;
1505- expect ( content ) . toContain ( 'Cache Lock Line 469' ) ;
1506-
1507- // Restore originals
1508- require ( '../lib/utils' ) . fileExists = originalFileExists ;
1509- require ( '../lib/lockfile' ) . isLocked = originalIsLocked ;
1510- done ( ) ;
1511- } ) ;
1512- } ) ;
15131304
15141305 test ( 'should parse parent template names with file extensions' , ( done ) => {
15151306 // Test parseParent with parent template that has file extension
0 commit comments