@@ -1155,76 +1155,157 @@ describe('platform-server partial hydration integration', () => {
11551155 } ) ;
11561156 } ) ;
11571157
1158- it ( 'timer' , async ( ) => {
1159- @Component ( {
1160- selector : 'app' ,
1161- template : `
1162- <main (click)="fnA()">
1163- @defer (hydrate on timer(500)) {
1164- <article>
1165- defer block rendered!
1166- <span id="test" (click)="fnB()">{{value()}}</span>
1167- </article>
1168- } @placeholder {
1169- <span>Outer block placeholder</span>
1170- }
1171- </main>
1172- ` ,
1173- } )
1174- class SimpleComponent {
1175- value = signal ( 'start' ) ;
1176- fnA ( ) { }
1177- fnB ( ) {
1178- this . value . set ( 'end' ) ;
1158+ describe ( 'timer' , ( ) => {
1159+ it ( 'top level timer' , async ( ) => {
1160+ @Component ( {
1161+ selector : 'app' ,
1162+ template : `
1163+ <main (click)="fnA()">
1164+ @defer (hydrate on timer(500)) {
1165+ <article>
1166+ defer block rendered!
1167+ <span id="test" (click)="fnB()">{{value()}}</span>
1168+ </article>
1169+ } @placeholder {
1170+ <span>Outer block placeholder</span>
1171+ }
1172+ </main>
1173+ ` ,
1174+ } )
1175+ class SimpleComponent {
1176+ value = signal ( 'start' ) ;
1177+ fnA ( ) { }
1178+ fnB ( ) {
1179+ this . value . set ( 'end' ) ;
1180+ }
11791181 }
1180- }
11811182
1182- const appId = 'custom-app-id' ;
1183- const providers = [ { provide : APP_ID , useValue : appId } ] ;
1184- const hydrationFeatures = ( ) => [ withIncrementalHydration ( ) ] ;
1183+ const appId = 'custom-app-id' ;
1184+ const providers = [ { provide : APP_ID , useValue : appId } ] ;
1185+ const hydrationFeatures = ( ) => [ withIncrementalHydration ( ) ] ;
11851186
1186- const html = await ssr ( SimpleComponent , { envProviders : providers , hydrationFeatures} ) ;
1187- const ssrContents = getAppContents ( html ) ;
1187+ const html = await ssr ( SimpleComponent , { envProviders : providers , hydrationFeatures} ) ;
1188+ const ssrContents = getAppContents ( html ) ;
11881189
1189- // <main> uses "eager" `custom-app-id` namespace.
1190- expect ( ssrContents ) . toContain ( '<main jsaction="click:;' ) ;
1191- // <div>s inside a defer block have `d0` as a namespace.
1192- expect ( ssrContents ) . toContain ( '<article>' ) ;
1193- // Outer defer block is rendered.
1194- expect ( ssrContents ) . toContain ( 'defer block rendered' ) ;
1190+ // <main> uses "eager" `custom-app-id` namespace.
1191+ expect ( ssrContents ) . toContain ( '<main jsaction="click:;' ) ;
1192+ // <div>s inside a defer block have `d0` as a namespace.
1193+ expect ( ssrContents ) . toContain ( '<article>' ) ;
1194+ // Outer defer block is rendered.
1195+ expect ( ssrContents ) . toContain ( 'defer block rendered' ) ;
11951196
1196- // Internal cleanup before we do server->client transition in this test.
1197- resetTViewsFor ( SimpleComponent ) ;
1197+ // Internal cleanup before we do server->client transition in this test.
1198+ resetTViewsFor ( SimpleComponent ) ;
11981199
1199- ////////////////////////////////
1200- const doc = getDocument ( ) ;
1201- const appRef = await prepareEnvironmentAndHydrate ( doc , html , SimpleComponent , {
1202- envProviders : [ ...providers , { provide : PLATFORM_ID , useValue : 'browser' } ] ,
1203- hydrationFeatures,
1200+ ////////////////////////////////
1201+ const doc = getDocument ( ) ;
1202+ const appRef = await prepareEnvironmentAndHydrate ( doc , html , SimpleComponent , {
1203+ envProviders : [ ...providers , { provide : PLATFORM_ID , useValue : 'browser' } ] ,
1204+ hydrationFeatures,
1205+ } ) ;
1206+ const compRef = getComponentRef < SimpleComponent > ( appRef ) ;
1207+ appRef . tick ( ) ;
1208+ await appRef . whenStable ( ) ;
1209+
1210+ const appHostNode = compRef . location . nativeElement ;
1211+
1212+ expect ( appHostNode . outerHTML ) . toContain ( '<article>' ) ;
1213+
1214+ await timeout ( 500 ) ; // wait for timer
1215+ appRef . tick ( ) ;
1216+
1217+ await allPendingDynamicImports ( ) ;
1218+ appRef . tick ( ) ;
1219+
1220+ expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">start</span>' ) ;
1221+
1222+ const testElement = doc . getElementById ( 'test' ) ! ;
1223+ const clickEvent2 = new CustomEvent ( 'click' ) ;
1224+ testElement . dispatchEvent ( clickEvent2 ) ;
1225+
1226+ appRef . tick ( ) ;
1227+
1228+ expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">end</span>' ) ;
12041229 } ) ;
1205- const compRef = getComponentRef < SimpleComponent > ( appRef ) ;
1206- appRef . tick ( ) ;
1207- await appRef . whenStable ( ) ;
12081230
1209- const appHostNode = compRef . location . nativeElement ;
1231+ it ( 'nested timer' , async ( ) => {
1232+ @Component ( {
1233+ selector : 'app' ,
1234+ template : `
1235+ <main (click)="fnA()">
1236+ @defer (on viewport; hydrate on interaction) {
1237+ <div id="main" (click)="fnA()">
1238+ defer block rendered!
1239+ @defer (on viewport; hydrate on timer(500)) {
1240+ <article>
1241+ <p id="nested">Nested defer block</p>
1242+ <span id="test" (click)="fnB()">{{value()}}</span>
1243+ </article>
1244+ } @placeholder {
1245+ <span>Inner block placeholder</span>
1246+ }
1247+ </div>
1248+ } @placeholder {
1249+ <span>Outer block placeholder</span>
1250+ }
1251+ </main>
1252+ ` ,
1253+ } )
1254+ class SimpleComponent {
1255+ value = signal ( 'start' ) ;
1256+ fnA ( ) { }
1257+ fnB ( ) {
1258+ this . value . set ( 'end' ) ;
1259+ }
1260+ }
12101261
1211- expect ( appHostNode . outerHTML ) . toContain ( '<article>' ) ;
1262+ const appId = 'custom-app-id' ;
1263+ const providers = [ { provide : APP_ID , useValue : appId } ] ;
1264+ const hydrationFeatures = ( ) => [ withIncrementalHydration ( ) ] ;
12121265
1213- await timeout ( 500 ) ; // wait for timer
1214- appRef . tick ( ) ;
1266+ const html = await ssr ( SimpleComponent , { envProviders : providers , hydrationFeatures } ) ;
1267+ const ssrContents = getAppContents ( html ) ;
12151268
1216- await allPendingDynamicImports ( ) ;
1217- appRef . tick ( ) ;
1269+ // <main> uses "eager" `custom-app-id` namespace.
1270+ expect ( ssrContents ) . toContain ( '<main jsaction="click:;' ) ;
1271+ // <div>s inside a defer block have `d0` as a namespace.
1272+ expect ( ssrContents ) . toContain ( '<article>' ) ;
1273+ // Outer defer block is rendered.
1274+ expect ( ssrContents ) . toContain ( 'defer block rendered' ) ;
12181275
1219- expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">start</span>' ) ;
1276+ // Internal cleanup before we do server->client transition in this test.
1277+ resetTViewsFor ( SimpleComponent ) ;
12201278
1221- const testElement = doc . getElementById ( 'test' ) ! ;
1222- const clickEvent2 = new CustomEvent ( 'click' ) ;
1223- testElement . dispatchEvent ( clickEvent2 ) ;
1279+ ////////////////////////////////
1280+ const doc = getDocument ( ) ;
1281+ const appRef = await prepareEnvironmentAndHydrate ( doc , html , SimpleComponent , {
1282+ envProviders : [ ...providers , { provide : PLATFORM_ID , useValue : 'browser' } ] ,
1283+ hydrationFeatures,
1284+ } ) ;
1285+ const compRef = getComponentRef < SimpleComponent > ( appRef ) ;
1286+ appRef . tick ( ) ;
1287+ await appRef . whenStable ( ) ;
12241288
1225- appRef . tick ( ) ;
1289+ const appHostNode = compRef . location . nativeElement ;
12261290
1227- expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">end</span>' ) ;
1291+ expect ( appHostNode . outerHTML ) . toContain ( '<article>' ) ;
1292+
1293+ await timeout ( 500 ) ; // wait for timer
1294+ appRef . tick ( ) ;
1295+
1296+ await allPendingDynamicImports ( ) ;
1297+ appRef . tick ( ) ;
1298+
1299+ expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">start</span>' ) ;
1300+
1301+ const testElement = doc . getElementById ( 'test' ) ! ;
1302+ const clickEvent2 = new CustomEvent ( 'click' ) ;
1303+ testElement . dispatchEvent ( clickEvent2 ) ;
1304+
1305+ appRef . tick ( ) ;
1306+
1307+ expect ( appHostNode . outerHTML ) . toContain ( '<span id="test">end</span>' ) ;
1308+ } ) ;
12281309 } ) ;
12291310
12301311 it ( 'when' , async ( ) => {
0 commit comments