@@ -3,7 +3,7 @@ import { ComponentFixtureAutoDetect, TestBed, fakeAsync, tick } from '@angular/c
3
3
import { first } from 'rxjs/operators' ;
4
4
5
5
// Testing api resources
6
- import { DynamicHooksComponent , LoadedComponent , anchorAttrHookId , anchorAttrParseToken , anchorElementTag , provideDynamicHooks } from '../testing-api' ;
6
+ import { ComponentConfig , DynamicHooksComponent , LoadedComponent , anchorAttrHookId , anchorAttrParseToken , anchorElementTag , provideDynamicHooks } from '../testing-api' ;
7
7
8
8
// Custom testing resources
9
9
import { defaultBeforeEach , prepareTestingModule , testParsers } from './shared' ;
@@ -45,7 +45,7 @@ describe('Component loading', () => {
45
45
it ( '#should ensure the passed componentConfig is correct' , ( ) => {
46
46
// Load with nonsensical componentConfig
47
47
expect ( ( ) => comp [ 'dynamicHooksService' ] [ 'componentCreator' ] . loadComponentClass ( true as any ) )
48
- . toThrow ( new Error ( 'The "component" property of a returned HookData object must either contain the component class or a LazyLoadComponentConfig' ) ) ;
48
+ . toThrow ( new Error ( 'The "component" property of a returned HookData object must either contain the component class, a function that returns a promise with the component class or an explicit LazyLoadComponentConfig' ) ) ;
49
49
} ) ;
50
50
51
51
it ( '#should be able to load module components' , ( ) => {
@@ -531,122 +531,132 @@ describe('Component loading', () => {
531
531
} ) ;
532
532
533
533
it ( '#should lazy-load components' , fakeAsync ( ( ) => {
534
- const genericMultiTagParser = TestBed . inject ( GenericMultiTagStringParser ) ;
535
- genericMultiTagParser . onGetBindings = ( hookId , hookValue , context ) => {
536
- return {
537
- inputs : {
538
- numberProp : 4
534
+
535
+ const testLazyLoading = ( lazyCompConfig : ComponentConfig ) => {
536
+
537
+ const genericMultiTagParser = TestBed . inject ( GenericMultiTagStringParser ) ;
538
+ genericMultiTagParser . onGetBindings = ( hookId , hookValue , context ) => {
539
+ return {
540
+ inputs : {
541
+ numberProp : 4
542
+ }
539
543
}
540
544
}
541
- }
542
545
543
- // Whatever parsers lazy-loads a component for this test
544
- const genericWhateverParser = TestBed . inject ( GenericWhateverStringParser ) ;
545
- genericWhateverParser . component = {
546
- // Simulate that loading this component takes 100ms
547
- importPromise : ( ) => new Promise ( resolve => setTimeout ( ( ) => {
548
- resolve ( { LazyTestComponent : LazyTestComponent } )
549
- } , 100 ) ) ,
550
- importName : 'LazyTestComponent'
551
- } ;
552
- genericWhateverParser . onGetBindings = ( hookId , hookValue , context ) => {
553
- return {
554
- inputs : {
555
- name : 'sleepy'
546
+ const genericSingleTagParser = TestBed . inject ( GenericSingleTagStringParser ) ;
547
+ genericSingleTagParser . onGetBindings = ( hookId , hookValue , context ) => {
548
+ return {
549
+ inputs : {
550
+ numberProp : 87
551
+ }
556
552
}
557
553
}
558
- }
559
554
560
- const genericSingleTagParser = TestBed . inject ( GenericSingleTagStringParser ) ;
561
- genericSingleTagParser . onGetBindings = ( hookId , hookValue , context ) => {
562
- return {
563
- inputs : {
564
- numberProp : 87
555
+ // Whatever parsers lazy-loads a component for this test
556
+ const genericWhateverParser = TestBed . inject ( GenericWhateverStringParser ) ;
557
+ genericWhateverParser . component = lazyCompConfig ;
558
+ genericWhateverParser . onGetBindings = ( hookId , hookValue , context ) => {
559
+ return {
560
+ inputs : {
561
+ name : 'sleepy'
562
+ }
565
563
}
566
564
}
567
- }
568
-
569
- const testText = `
570
- <p>
571
- A couple of components:
572
- [multitag-string]
573
- [whatever-string][/whatever-string]
574
- [/multitag-string]
575
- [singletag-string]
576
- </p>
577
- ` ;
578
-
579
- comp . content = testText ;
580
- comp . context = context ;
581
- let loadedComponents : LoadedComponent [ ] = [ ] ;
582
- comp . componentsLoaded . pipe ( first ( ) ) . subscribe ( ( lc : any ) => loadedComponents = lc ) ;
583
- comp . ngOnChanges ( { content : true , context : true } as any ) ;
584
565
585
- // Everything except the lazy-loaded component should be loaded
586
- expect ( fixture . nativeElement . querySelector ( '.multitag-component' ) ) . not . toBe ( null ) ;
587
- expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) ) . toBe ( null ) ;
588
- expect ( fixture . nativeElement . querySelector ( '.singletag-component' ) ) . not . toBe ( null ) ;
589
-
590
- expect ( Object . values ( comp . hookIndex ) . length ) . toBe ( 3 ) ;
591
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . constructor . name ) . toBe ( 'MultiTagTestComponent' ) ;
592
- expect ( comp . hookIndex [ 2 ] . componentRef ) . toBeNull ( ) ;
593
- expect ( comp . hookIndex [ 3 ] . componentRef ! . instance . constructor . name ) . toBe ( 'SingleTagTestComponent' ) ;
594
-
595
- // Make sure that onDynamicChanges has triggered on component init
596
- spyOn ( comp . hookIndex [ 1 ] . componentRef ! . instance , 'onDynamicChanges' ) . and . callThrough ( ) ;
597
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicChanges [ 'calls' ] . count ( ) ) . toBe ( 0 ) ;
598
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContext ) . toEqual ( context ) ;
599
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren ) . toBeUndefined ( ) ;
600
-
601
- // Make sure that onDynamicMount has not yet triggered
602
- spyOn ( comp . hookIndex [ 1 ] . componentRef ! . instance , 'onDynamicMount' ) . and . callThrough ( ) ;
603
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicMount [ 'calls' ] . count ( ) ) . toBe ( 0 ) ;
604
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContext ) . toBeUndefined ( ) ;
605
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren ) . toBeUndefined ( ) ;
606
-
607
- // Also, componentsLoaded should not yet have triggered
608
- expect ( loadedComponents ) . toEqual ( [ ] ) ;
609
-
610
- // Wait for imports via fakeAsync()'s tick() that synchronously advances time for testing
611
- // This didn't always work. Used to have to manually wait by using (done) => {} as the testing wrapper function isntead of faceAsync,
612
- // then wait via setTimeout() and call done() when testing is finished. This had the disadvantage of actually having to wait for the timeout
613
- tick ( 500 ) ;
614
-
615
- // Lazy-loaded component should be loaded by now in anchor
616
- expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) ) . not . toBe ( null ) ;
617
- expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) . parentElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
618
- expect ( comp . hookIndex [ 2 ] . componentRef ! . instance . constructor . name ) . toBe ( 'LazyTestComponent' ) ;
619
- expect ( comp . hookIndex [ 2 ] . componentRef ! . instance . name ) . toBe ( 'sleepy' ) ;
620
-
621
- // Make sure that onDynamicChanges has triggered again (with contentChildren)
622
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicChanges [ 'calls' ] . count ( ) ) . toBe ( 1 ) ;
623
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContext ) . toEqual ( context ) ;
624
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren . length ) . toBe ( 1 ) ;
625
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren [ 0 ] . componentRef . location . nativeElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
626
-
627
- // Make sure that onDynamicMount has triggered
628
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicMount [ 'calls' ] . count ( ) ) . toBe ( 1 ) ;
629
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContext ) . toEqual ( context ) ;
630
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren . length ) . toBe ( 1 ) ;
631
- expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren [ 0 ] . componentRef . location . nativeElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
632
-
633
- // ComponentsLoaded should have emitted now and contain the lazy-loaded component
634
- expect ( loadedComponents . length ) . toBe ( 3 ) ;
566
+ const testText = `
567
+ <p>
568
+ A couple of components:
569
+ [multitag-string]
570
+ [whatever-string][/whatever-string]
571
+ [/multitag-string]
572
+ [singletag-string]
573
+ </p>
574
+ ` ;
575
+
576
+ comp . content = testText ;
577
+ comp . context = context ;
578
+ let loadedComponents : LoadedComponent [ ] = [ ] ;
579
+ comp . componentsLoaded . pipe ( first ( ) ) . subscribe ( ( lc : any ) => loadedComponents = lc ) ;
580
+ comp . ngOnChanges ( { content : true , context : true } as any ) ;
581
+
582
+ // Everything except the lazy-loaded component should be loaded
583
+ expect ( fixture . nativeElement . querySelector ( '.multitag-component' ) ) . not . toBe ( null ) ;
584
+ expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) ) . toBe ( null ) ;
585
+ expect ( fixture . nativeElement . querySelector ( '.singletag-component' ) ) . not . toBe ( null ) ;
586
+
587
+ expect ( Object . values ( comp . hookIndex ) . length ) . toBe ( 3 ) ;
588
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . constructor . name ) . toBe ( 'MultiTagTestComponent' ) ;
589
+ expect ( comp . hookIndex [ 2 ] . componentRef ) . toBeNull ( ) ;
590
+ expect ( comp . hookIndex [ 3 ] . componentRef ! . instance . constructor . name ) . toBe ( 'SingleTagTestComponent' ) ;
591
+
592
+ // Make sure that onDynamicChanges has triggered on component init
593
+ spyOn ( comp . hookIndex [ 1 ] . componentRef ! . instance , 'onDynamicChanges' ) . and . callThrough ( ) ;
594
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicChanges [ 'calls' ] . count ( ) ) . toBe ( 0 ) ;
595
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContext ) . toEqual ( context ) ;
596
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren ) . toBeUndefined ( ) ;
597
+
598
+ // Make sure that onDynamicMount has not yet triggered
599
+ spyOn ( comp . hookIndex [ 1 ] . componentRef ! . instance , 'onDynamicMount' ) . and . callThrough ( ) ;
600
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicMount [ 'calls' ] . count ( ) ) . toBe ( 0 ) ;
601
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContext ) . toBeUndefined ( ) ;
602
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren ) . toBeUndefined ( ) ;
603
+
604
+ // Also, componentsLoaded should not yet have triggered
605
+ expect ( loadedComponents ) . toEqual ( [ ] ) ;
606
+
607
+ // Wait for imports via fakeAsync()'s tick() that synchronously advances time for testing
608
+ // This didn't always work. Used to have to manually wait by using (done) => {} as the testing wrapper function isntead of faceAsync,
609
+ // then wait via setTimeout() and call done() when testing is finished. This had the disadvantage of actually having to wait for the timeout
610
+ tick ( 500 ) ;
611
+
612
+ // Lazy-loaded component should be loaded by now in anchor
613
+ expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) ) . not . toBe ( null ) ;
614
+ expect ( fixture . nativeElement . querySelector ( '.lazy-component' ) . parentElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
615
+ expect ( comp . hookIndex [ 2 ] . componentRef ! . instance . constructor . name ) . toBe ( 'LazyTestComponent' ) ;
616
+ expect ( comp . hookIndex [ 2 ] . componentRef ! . instance . name ) . toBe ( 'sleepy' ) ;
617
+
618
+ // Make sure that onDynamicChanges has triggered again (with contentChildren)
619
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicChanges [ 'calls' ] . count ( ) ) . toBe ( 1 ) ;
620
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContext ) . toEqual ( context ) ;
621
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren . length ) . toBe ( 1 ) ;
622
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . changesContentChildren [ 0 ] . componentRef . location . nativeElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
623
+
624
+ // Make sure that onDynamicMount has triggered
625
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . onDynamicMount [ 'calls' ] . count ( ) ) . toBe ( 1 ) ;
626
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContext ) . toEqual ( context ) ;
627
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren . length ) . toBe ( 1 ) ;
628
+ expect ( comp . hookIndex [ 1 ] . componentRef ! . instance . mountContentChildren [ 0 ] . componentRef . location . nativeElement . tagName ) . toBe ( anchorElementTag . toUpperCase ( ) ) ;
629
+
630
+ // ComponentsLoaded should have emitted now and contain the lazy-loaded component
631
+ expect ( loadedComponents . length ) . toBe ( 3 ) ;
632
+
633
+ expect ( loadedComponents [ 0 ] . hookId ) . toBe ( 1 ) ;
634
+ expect ( loadedComponents [ 0 ] . hookValue ) . toEqual ( { openingTag : `[multitag-string]` , closingTag : `[/multitag-string]` , element : null , elementSnapshot : null } ) ;
635
+ expect ( loadedComponents [ 0 ] . hookParser ) . toBeDefined ( ) ;
636
+ expect ( loadedComponents [ 0 ] . componentRef . instance . numberProp ) . toBe ( 4 ) ;
637
+
638
+ expect ( loadedComponents [ 1 ] . hookId ) . toBe ( 2 ) ;
639
+ expect ( loadedComponents [ 1 ] . hookValue ) . toEqual ( { openingTag : `[whatever-string]` , closingTag : `[/whatever-string]` , element : null , elementSnapshot : null } ) ;
640
+ expect ( loadedComponents [ 1 ] . hookParser ) . toBeDefined ( ) ;
641
+ expect ( loadedComponents [ 1 ] . componentRef . instance . name ) . toBe ( 'sleepy' ) ;
642
+
643
+ expect ( loadedComponents [ 2 ] . hookId ) . toBe ( 3 ) ;
644
+ expect ( loadedComponents [ 2 ] . hookValue ) . toEqual ( { openingTag : `[singletag-string]` , closingTag : null , element : null , elementSnapshot : null } ) ;
645
+ expect ( loadedComponents [ 2 ] . hookParser ) . toBeDefined ( ) ;
646
+ expect ( loadedComponents [ 2 ] . componentRef . instance . numberProp ) . toBe ( 87 ) ;
647
+ }
635
648
636
- expect ( loadedComponents [ 0 ] . hookId ) . toBe ( 1 ) ;
637
- expect ( loadedComponents [ 0 ] . hookValue ) . toEqual ( { openingTag : `[multitag-string]` , closingTag : `[/multitag-string]` , element : null , elementSnapshot : null } ) ;
638
- expect ( loadedComponents [ 0 ] . hookParser ) . toBeDefined ( ) ;
639
- expect ( loadedComponents [ 0 ] . componentRef . instance . numberProp ) . toBe ( 4 ) ;
649
+ // Test with function that returns promise with component class directly
650
+ testLazyLoading ( ( ) =>
651
+ new Promise ( resolve => setTimeout ( ( ) => resolve ( { LazyTestComponent : LazyTestComponent } ) , 100 ) )
652
+ . then ( ( m : any ) => m . LazyTestComponent ) )
640
653
641
- expect ( loadedComponents [ 1 ] . hookId ) . toBe ( 2 ) ;
642
- expect ( loadedComponents [ 1 ] . hookValue ) . toEqual ( { openingTag : `[whatever-string]` , closingTag : `[/whatever-string]` , element : null , elementSnapshot : null } ) ;
643
- expect ( loadedComponents [ 1 ] . hookParser ) . toBeDefined ( ) ;
644
- expect ( loadedComponents [ 1 ] . componentRef . instance . name ) . toBe ( 'sleepy' ) ;
654
+ // Test with explicit LazyLoadComponentConfig
655
+ testLazyLoading ( {
656
+ importPromise : ( ) => new Promise ( resolve => setTimeout ( ( ) => resolve ( { LazyTestComponent : LazyTestComponent } ) , 100 ) ) ,
657
+ importName : 'LazyTestComponent'
658
+ } ) ;
645
659
646
- expect ( loadedComponents [ 2 ] . hookId ) . toBe ( 3 ) ;
647
- expect ( loadedComponents [ 2 ] . hookValue ) . toEqual ( { openingTag : `[singletag-string]` , closingTag : null , element : null , elementSnapshot : null } ) ;
648
- expect ( loadedComponents [ 2 ] . hookParser ) . toBeDefined ( ) ;
649
- expect ( loadedComponents [ 2 ] . componentRef . instance . numberProp ) . toBe ( 87 ) ;
650
660
} ) ) ;
651
661
652
662
it ( '#should check that the "importPromise"-field of lazy-loaded parsers is not the promise itself' , ( ) => {
0 commit comments