11import { BrowserModule , provideClientHydration } from '@angular/platform-browser' ;
22import {
3- Component , destroyPlatform , NgModule , PLATFORM_ID , VERSION , importProvidersFrom ,
3+ Component ,
4+ destroyPlatform ,
5+ NgModule ,
6+ PLATFORM_ID ,
7+ importProvidersFrom ,
48} from '@angular/core' ;
5- import { provideServerRendering , ServerModule } from '@angular/platform-server' ;
9+ import { ServerModule , renderModule } from '@angular/platform-server' ;
610import { DxServerModule } from 'devextreme-angular/server' ;
711import infernoRenderer from 'devextreme/core/inferno_renderer' ;
812import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' ;
913import { DevExtremeModule } from 'devextreme-angular' ;
10- import { componentNames } from './component-names' ;
14+ import { componentNames as componentNamesAll } from './component-names' ;
15+
16+ const componentNames = componentNamesAll . filter ( ( n ) => [ 'toast' , 'action-sheet' ] . includes ( n ) ) ;
1117
1218const containerClass = 'container' ;
1319const containerSelector = `.${ containerClass } ` ;
@@ -35,20 +41,13 @@ class AppBrowserModule {}
3541 bootstrap : [ AppComponent ] ,
3642 providers : [
3743 provideClientHydration ( ) ,
38- provideServerRendering ( ) ,
3944 { provide : PLATFORM_ID , useValue : 'server' } ,
4045 importProvidersFrom ( DxServerModule ) ,
4146 ] ,
4247} )
4348class AppSSRModule { }
4449
4550class TestHelpers {
46- static createSSRBodyMarkup ( ssrComponentsHTML : string ) : string {
47- const nghData = '[{}]' ;
48- return `<!--nghm--><app-root ng-version="${ VERSION . full } " ngh="0" ng-server-context="ssg">${ ssrComponentsHTML } </app-root>
49- <script id="ng-state" type="application/json">{"DX_isPlatformServer":true,"__nghData__":${ nghData } }</script>` ;
50- }
51-
5251 static normalizeClassNames ( element : HTMLElement ) : void {
5352 const classNames = Array . from ( element . classList ) . sort ( ) ;
5453 // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -57,23 +56,8 @@ class TestHelpers {
5756 element . classList . add ( ...classNames ) ;
5857 }
5958
60- static compareContainers ( ssrContainer : HTMLElement , hydratedContainer : HTMLElement ) : [ string , string ] {
61- const selector = `${ containerSelector } > *` ;
62-
63- [ ssrContainer , hydratedContainer ] . forEach ( ( container ) => {
64- container . querySelectorAll ( selector ) . forEach ( ( el ) => {
65- this . normalizeClassNames ( el as HTMLElement ) ;
66- } ) ;
67- } ) ;
68-
69- return [ ssrContainer . innerHTML , hydratedContainer . innerHTML ] ;
70- }
71-
7259 static hasConsoleMessage ( spy : jasmine . Spy , messages : string [ ] ) : boolean {
73- return spy . calls . allArgs ( ) . some ( ( args ) => messages . some ( ( msg ) => {
74- console . log ( '-----args[0]----->' , args [ 0 ] ) ;
75- return args [ 0 ] . toLowerCase ( ) . includes ( msg . toLowerCase ( ) )
76- } ) ) ;
60+ return spy . calls . allArgs ( ) . some ( ( args ) => messages . some ( ( msg ) => args [ 0 ] . toLowerCase ( ) . includes ( msg . toLowerCase ( ) ) ) ) ;
7761 }
7862}
7963
@@ -84,11 +68,11 @@ describe('Angular Components Hydration Test', () => {
8468 log : jasmine . Spy ;
8569 } ;
8670 const ssrState : {
87- body : HTMLElement | null ;
8871 containerHtml : string ;
72+ ssrHTML : string ;
8973 } = {
90- body : null ,
9174 containerHtml : '' ,
75+ ssrHTML : '' ,
9276 } ;
9377
9478 beforeAll ( ( ) => {
@@ -109,37 +93,39 @@ describe('Angular Components Hydration Test', () => {
10993 } ) ;
11094
11195 it ( 'should generate correct SSR HTML' , async ( ) => {
112- document . body . innerHTML = '<app-root></app-root>' ;
96+ const html = await renderModule ( AppSSRModule , {
97+ document : '<!DOCTYPE html><html><head></head><body><app-root></app-root></body></html>' ,
98+ url : '/' ,
99+ } ) ;
113100
114- // Act
115- await platformBrowserDynamic ( ) . bootstrapModule ( AppSSRModule ) ;
101+ ssrState . ssrHTML = html
102+ //.replace(/ng-server-context="other"/g, 'ng-server-context="ssg"')
103+ . replace ( / ^ .* < b o d y / , '<body' )
104+ . replace ( / < \/ b o d y > .* $ / , '</body>' ) ;
105+
106+ const tempDiv = document . createElement ( 'div' ) ;
107+ tempDiv . innerHTML = ssrState . ssrHTML ;
116108
117109 // Assert
118- ssrState . body = document . body ;
119- ssrState . containerHtml = document . querySelector ( `${ containerSelector } ` ) ?. outerHTML ?? '' ;
110+ ssrState . containerHtml = tempDiv . querySelector ( `${ containerSelector } ` ) ?. innerHTML ?? '' ;
120111
121- console . log ( '-------ssrState.containerHtml--->' , ssrState . containerHtml ) ;
122112 expect ( ssrState . containerHtml ) . toBeTruthy ( ) ;
113+ expect ( ssrState . ssrHTML ) . toBeTruthy ( ) ;
123114 } ) ;
124115
125116 it ( 'should correctly hydrate server-rendered HTML' , async ( ) => {
126117 infernoRenderer . resetInjection ( ) ;
127- document . body . innerHTML = TestHelpers . createSSRBodyMarkup ( ssrState . containerHtml ) ;
128-
118+
119+ document . body . outerHTML = ssrState . ssrHTML ;
120+
129121 // Act
130122 await platformBrowserDynamic ( ) . bootstrapModule ( AppBrowserModule ) ;
131123
132- // Assert
133- const [ ssrResult , hydratedResult ] = TestHelpers . compareContainers (
134- ssrState . body . querySelector ( `${ containerSelector } ` ) ,
135- document . querySelector ( `${ containerSelector } ` ) ,
136- ) ;
137-
138124 expect ( TestHelpers . hasConsoleMessage (
139125 consoleSpies . log ,
140126 [ 'Angular hydrated 1 component(s)' ] ,
141127 ) ) . toBeTruthy ( ) ;
142128
143- expect ( ssrResult ) . toEqual ( hydratedResult ) ;
129+ expect ( ssrState . containerHtml ) . toEqual ( document . querySelector ( ` ${ containerSelector } ` ) . innerHTML ) ;
144130 } ) ;
145131} ) ;
0 commit comments