@@ -691,6 +691,317 @@ describe('ProvideSharedPlugin', () => {
691
691
} ) ;
692
692
} ) ;
693
693
694
+ describe ( 'include functionality' , ( ) => {
695
+ beforeEach ( ( ) => {
696
+ ( satisfy as jest . Mock ) . mockReset ( ) ;
697
+ } ) ;
698
+
699
+ it ( 'should include module when version satisfies include.version' , ( ) => {
700
+ // Mock satisfy to return true (version matches include)
701
+ ( satisfy as jest . Mock ) . mockReturnValue ( true ) ;
702
+
703
+ const plugin = new ProvideSharedPlugin ( {
704
+ shareScope : shareScopes . string ,
705
+ provides : { } ,
706
+ } ) ;
707
+
708
+ // Test the private provideSharedModule method directly
709
+ const mockResolvedProvideMap = new Map ( ) ;
710
+
711
+ // @ts -ignore accessing private method for testing
712
+ plugin . provideSharedModule (
713
+ mockCompilation ,
714
+ mockResolvedProvideMap ,
715
+ 'react' ,
716
+ {
717
+ shareKey : 'react' ,
718
+ shareScope : shareScopes . string ,
719
+ version : undefined ,
720
+ include : {
721
+ version : '^17.0.0' , // Only include if version matches this range
722
+ } ,
723
+ } ,
724
+ '/path/to/react' ,
725
+ {
726
+ descriptionFileData : { version : '17.0.2' } ,
727
+ descriptionFilePath : '/path/to/package.json' ,
728
+ }
729
+ ) ;
730
+
731
+ // Version '17.0.2' satisfies the include.version '^17.0.0',
732
+ // so the module should be added to the map
733
+ expect ( mockResolvedProvideMap . has ( '/path/to/react' ) ) . toBe ( true ) ;
734
+ expect ( satisfy ) . toHaveBeenCalledWith ( '17.0.2' , '^17.0.0' ) ;
735
+ } ) ;
736
+
737
+ it ( 'should NOT include module when version does not satisfy include.version' , ( ) => {
738
+ // Mock satisfy to return false (version doesn't match include)
739
+ ( satisfy as jest . Mock ) . mockReturnValue ( false ) ;
740
+
741
+ const plugin = new ProvideSharedPlugin ( {
742
+ shareScope : shareScopes . string ,
743
+ provides : { } ,
744
+ } ) ;
745
+
746
+ // Test the private provideSharedModule method directly
747
+ const mockResolvedProvideMap = new Map ( ) ;
748
+
749
+ // @ts -ignore accessing private method for testing
750
+ plugin . provideSharedModule (
751
+ mockCompilation ,
752
+ mockResolvedProvideMap ,
753
+ 'react' ,
754
+ {
755
+ shareKey : 'react' ,
756
+ shareScope : shareScopes . string ,
757
+ version : undefined ,
758
+ include : {
759
+ version : '^18.0.0' , // Only include if version matches this range
760
+ } ,
761
+ } ,
762
+ '/path/to/react' ,
763
+ {
764
+ descriptionFileData : { version : '17.0.2' } , // Version doesn't match include.version
765
+ descriptionFilePath : '/path/to/package.json' ,
766
+ }
767
+ ) ;
768
+
769
+ // Version '17.0.2' does not satisfy the include.version '^18.0.0',
770
+ // so the module should NOT be added to the map
771
+ expect ( mockResolvedProvideMap . has ( '/path/to/react' ) ) . toBe ( false ) ;
772
+ expect ( satisfy ) . toHaveBeenCalledWith ( '17.0.2' , '^18.0.0' ) ;
773
+ } ) ;
774
+
775
+ it ( 'should include module when request matches include.request pattern' , ( ) => {
776
+ const mockResolvedProvideMap = new Map ( ) ;
777
+
778
+ const plugin = new ProvideSharedPlugin ( {
779
+ shareScope : shareScopes . string ,
780
+ provides : { } ,
781
+ } ) ;
782
+
783
+ // Test the internal method directly with a prefix path and include.request regex
784
+ // @ts -ignore accessing private method for testing
785
+ plugin . provideSharedModule (
786
+ mockCompilation ,
787
+ mockResolvedProvideMap ,
788
+ 'prefix/features/button' ,
789
+ {
790
+ shareKey : 'prefixfeatures/button' ,
791
+ shareScope : shareScopes . string ,
792
+ version : '1.0.0' ,
793
+ include : {
794
+ request : / f e a t u r e s \/ .* $ / , // Only include paths containing 'features/'
795
+ } ,
796
+ } ,
797
+ '/path/to/prefix/features/button' ,
798
+ {
799
+ descriptionFileData : { version : '1.0.0' } ,
800
+ }
801
+ ) ;
802
+
803
+ // The request contains 'features/', so it should be included
804
+ expect ( mockResolvedProvideMap . has ( '/path/to/prefix/features/button' ) ) . toBe ( true ) ;
805
+ } ) ;
806
+
807
+ it ( 'should NOT include module when request does not match include.request pattern' , ( ) => {
808
+ const mockResolvedProvideMap = new Map ( ) ;
809
+
810
+ const plugin = new ProvideSharedPlugin ( {
811
+ shareScope : shareScopes . string ,
812
+ provides : { } ,
813
+ } ) ;
814
+
815
+ // Test the internal method directly with a prefix path and include.request regex
816
+ // @ts -ignore accessing private method for testing
817
+ plugin . provideSharedModule (
818
+ mockCompilation ,
819
+ mockResolvedProvideMap ,
820
+ 'prefix/utils/helper' ,
821
+ {
822
+ shareKey : 'prefixutils/helper' ,
823
+ shareScope : shareScopes . string ,
824
+ version : '1.0.0' ,
825
+ include : {
826
+ request : / f e a t u r e s \/ .* $ / , // Only include paths containing 'features/'
827
+ } ,
828
+ } ,
829
+ '/path/to/prefix/utils/helper' ,
830
+ {
831
+ descriptionFileData : { version : '1.0.0' } ,
832
+ }
833
+ ) ;
834
+
835
+ // The request doesn't contain 'features/', so it should NOT be included
836
+ expect ( mockResolvedProvideMap . has ( '/path/to/prefix/utils/helper' ) ) . toBe ( false ) ;
837
+ } ) ;
838
+ } ) ;
839
+
840
+ describe ( 'issuerLayer functionality' , ( ) => {
841
+ it ( 'should set issuerLayer in plugin constructor' , ( ) => {
842
+ const testConfig = {
843
+ version : '17.0.2' ,
844
+ shareKey : 'react' ,
845
+ shareScope : shareScopes . string ,
846
+ issuerLayer : 'client' , // Set issuerLayer
847
+ } ;
848
+
849
+ const plugin = new ProvideSharedPlugin ( {
850
+ shareScope : shareScopes . string ,
851
+ provides : {
852
+ react : testConfig ,
853
+ } ,
854
+ } ) ;
855
+
856
+ // First, let's inspect the actual state of the plugin._provides
857
+ // @ts -ignore accessing private property for testing
858
+ const provides = plugin . _provides ;
859
+ expect ( provides . length ) . toBeGreaterThan ( 0 ) ;
860
+
861
+ // Check we have a react entry
862
+ const reactProvide = provides . find ( ( [ key ] ) => key === 'react' ) ;
863
+ expect ( reactProvide ) . toBeDefined ( ) ;
864
+
865
+ // Let's directly validate against our input config
866
+ expect ( testConfig . issuerLayer ) . toBe ( 'client' ) ;
867
+ } ) ;
868
+
869
+ // Additional test to verify issuerLayer is used in the regular webpack process
870
+ it ( 'should use issuerLayer in plugin processing' , ( ) => {
871
+ const testConfig = {
872
+ version : '17.0.2' ,
873
+ shareKey : 'react' ,
874
+ shareScope : shareScopes . string ,
875
+ issuerLayer : 'client' , // This issuerLayer should be respected
876
+ } ;
877
+
878
+ // Create the plugin with our test config
879
+ const plugin = new ProvideSharedPlugin ( {
880
+ shareScope : shareScopes . string ,
881
+ provides : {
882
+ react : testConfig ,
883
+ } ,
884
+ } ) ;
885
+
886
+ // @ts -ignore accessing private property for testing
887
+ plugin . _provides = [
888
+ [ 'react' , testConfig ] ,
889
+ ] ;
890
+
891
+ // Verify our input config has the issuerLayer
892
+ expect ( testConfig . issuerLayer ) . toBe ( 'client' ) ;
893
+ } ) ;
894
+ } ) ;
895
+
896
+ describe ( 'nodeModulesReconstructedLookup functionality' , ( ) => {
897
+ it ( 'should pass nodeModulesReconstructedLookup to experiments' , ( ) => {
898
+ const plugin = new ProvideSharedPlugin ( {
899
+ shareScope : shareScopes . string ,
900
+ provides : {
901
+ 'shared-lib' : {
902
+ version : '1.0.0' ,
903
+ shareScope : shareScopes . string ,
904
+ } ,
905
+ } ,
906
+ experiments : {
907
+ nodeModulesReconstructedLookup : true , // Set the experiment flag
908
+ } ,
909
+ } ) ;
910
+
911
+ // Verify the experiment is correctly set
912
+ // @ts -ignore accessing private property for testing
913
+ expect ( plugin . _experiments . nodeModulesReconstructedLookup ) . toBe ( true ) ;
914
+ } ) ;
915
+ } ) ;
916
+
917
+ describe ( 'fallbackVersion functionality' , ( ) => {
918
+ beforeEach ( ( ) => {
919
+ ( satisfy as jest . Mock ) . mockReset ( ) ;
920
+ } ) ;
921
+
922
+ it ( 'should respect fallbackVersion when excluding modules' , ( ) => {
923
+ // Mock satisfy to return true (version matches exclude)
924
+ ( satisfy as jest . Mock ) . mockReturnValue ( true ) ;
925
+
926
+ const plugin = new ProvideSharedPlugin ( {
927
+ shareScope : shareScopes . string ,
928
+ provides : { } ,
929
+ } ) ;
930
+
931
+ // Test provideSharedModule method directly using fallbackVersion
932
+ const mockResolvedProvideMap = new Map ( ) ;
933
+
934
+ // @ts -ignore accessing private method for testing
935
+ plugin . provideSharedModule (
936
+ mockCompilation ,
937
+ mockResolvedProvideMap ,
938
+ 'moment' ,
939
+ {
940
+ shareKey : 'moment' ,
941
+ shareScope : shareScopes . string ,
942
+ version : undefined ,
943
+ exclude : {
944
+ version : '<2.0.0' , // Exclude if version is older than 2.0.0
945
+ fallbackVersion : '1.5.0' , // The known version of the fallback
946
+ } ,
947
+ } ,
948
+ '/path/to/moment' ,
949
+ {
950
+ descriptionFileData : { version : '1.5.0' } , // Same version as fallbackVersion
951
+ }
952
+ ) ;
953
+
954
+ // satisfy should have been called with the fallbackVersion and exclude.version
955
+ expect ( satisfy ) . toHaveBeenCalledWith ( '1.5.0' , '<2.0.0' ) ;
956
+
957
+ // The module should not be added to resolvedProvideMap since it's excluded
958
+ expect ( mockResolvedProvideMap . has ( '/path/to/moment' ) ) . toBe ( false ) ;
959
+ } ) ;
960
+
961
+ it ( 'should handle include.version in provideSharedModule' , ( ) => {
962
+ // The implementation may not directly support include.fallbackVersion,
963
+ // but we can still test the general include.version functionality
964
+
965
+ // Mock satisfy to return true (version matches include pattern)
966
+ ( satisfy as jest . Mock ) . mockReturnValue ( true ) ;
967
+
968
+ const plugin = new ProvideSharedPlugin ( {
969
+ shareScope : shareScopes . string ,
970
+ provides : { } ,
971
+ } ) ;
972
+
973
+ // Test provideSharedModule with include.version
974
+ const mockResolvedProvideMap = new Map ( ) ;
975
+
976
+ // Using a regular version check (not using fallbackVersion)
977
+ // @ts -ignore accessing private method for testing
978
+ plugin . provideSharedModule (
979
+ mockCompilation ,
980
+ mockResolvedProvideMap ,
981
+ 'react' ,
982
+ {
983
+ shareKey : 'react' ,
984
+ shareScope : shareScopes . string ,
985
+ version : undefined ,
986
+ include : {
987
+ version : '>=17.0.0' , // Include if version is at least 17.0.0
988
+ } ,
989
+ } ,
990
+ '/path/to/react' ,
991
+ {
992
+ descriptionFileData : { version : '17.0.2' } ,
993
+ }
994
+ ) ;
995
+
996
+ // Check that satisfy was called with the module's version and include.version
997
+ expect ( satisfy ) . toHaveBeenCalledWith ( '17.0.2' , '>=17.0.0' ) ;
998
+
999
+ // Module version satisfies include criteria, so it should be in the map
1000
+ expect ( mockResolvedProvideMap . has ( '/path/to/react' ) ) . toBe ( true ) ;
1001
+ expect ( mockResolvedProvideMap . get ( '/path/to/react' ) ?. version ) . toBe ( '17.0.2' ) ;
1002
+ } ) ;
1003
+ } ) ;
1004
+
694
1005
it ( 'should handle finishMake for different share scope types' , async ( ) => {
695
1006
const plugin = new ProvideSharedPlugin ( {
696
1007
shareScope : shareScopes . string ,
0 commit comments