@@ -966,4 +966,304 @@ describe('FragmentRefs', () => {
966
966
expect ( fragmentHandle . getRootNode ( ) ) . toBe ( fragmentHandle ) ;
967
967
} ) ;
968
968
} ) ;
969
+
970
+ describe ( 'compareDocumentPosition' , ( ) => {
971
+ function expectPosition ( position , spec ) {
972
+ expect ( ( position & Node . DOCUMENT_POSITION_PRECEDING ) !== 0 ) . toBe (
973
+ spec . preceding ,
974
+ ) ;
975
+ expect ( ( position & Node . DOCUMENT_POSITION_FOLLOWING ) !== 0 ) . toBe (
976
+ spec . following ,
977
+ ) ;
978
+ expect ( ( position & Node . DOCUMENT_POSITION_CONTAINS ) !== 0 ) . toBe (
979
+ spec . contains ,
980
+ ) ;
981
+ expect ( ( position & Node . DOCUMENT_POSITION_CONTAINED_BY ) !== 0 ) . toBe (
982
+ spec . containedBy ,
983
+ ) ;
984
+ expect ( ( position & Node . DOCUMENT_POSITION_DISCONNECTED ) !== 0 ) . toBe (
985
+ spec . disconnected ,
986
+ ) ;
987
+ expect (
988
+ ( position & Node . DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC ) !== 0 ,
989
+ ) . toBe ( spec . implementationSpecific ) ;
990
+ }
991
+ // @gate enableFragmentRefs
992
+ it ( 'returns the relationship between the fragment instance and a given node' , async ( ) => {
993
+ const fragmentRef = React . createRef ( ) ;
994
+ const beforeRef = React . createRef ( ) ;
995
+ const afterRef = React . createRef ( ) ;
996
+ const middleChildRef = React . createRef ( ) ;
997
+ const firstChildRef = React . createRef ( ) ;
998
+ const lastChildRef = React . createRef ( ) ;
999
+ const containerRef = React . createRef ( ) ;
1000
+ const disconnectedElement = document . createElement ( 'div' ) ;
1001
+ const root = ReactDOMClient . createRoot ( container ) ;
1002
+
1003
+ function Test ( ) {
1004
+ return (
1005
+ < div ref = { containerRef } >
1006
+ < div ref = { beforeRef } />
1007
+ < React . Fragment ref = { fragmentRef } >
1008
+ < div ref = { firstChildRef } />
1009
+ < div ref = { middleChildRef } />
1010
+ < div ref = { lastChildRef } />
1011
+ </ React . Fragment >
1012
+ < div ref = { afterRef } />
1013
+ </ div >
1014
+ ) ;
1015
+ }
1016
+
1017
+ await act ( ( ) => root . render ( < Test /> ) ) ;
1018
+
1019
+ // document.body is preceding and contains the fragment
1020
+ expectPosition (
1021
+ fragmentRef . current . compareDocumentPosition ( document . body ) ,
1022
+ {
1023
+ preceding : true ,
1024
+ following : false ,
1025
+ contains : true ,
1026
+ containedBy : false ,
1027
+ disconnected : false ,
1028
+ implementationSpecific : false ,
1029
+ } ,
1030
+ ) ;
1031
+
1032
+ // beforeRef is preceding the fragment
1033
+ expectPosition (
1034
+ fragmentRef . current . compareDocumentPosition ( beforeRef . current ) ,
1035
+ {
1036
+ preceding : true ,
1037
+ following : false ,
1038
+ contains : false ,
1039
+ containedBy : false ,
1040
+ disconnected : false ,
1041
+ implementationSpecific : false ,
1042
+ } ,
1043
+ ) ;
1044
+
1045
+ // afterRef is following the fragment
1046
+ expectPosition (
1047
+ fragmentRef . current . compareDocumentPosition ( afterRef . current ) ,
1048
+ {
1049
+ preceding : false ,
1050
+ following : true ,
1051
+ contains : false ,
1052
+ containedBy : false ,
1053
+ disconnected : false ,
1054
+ implementationSpecific : false ,
1055
+ } ,
1056
+ ) ;
1057
+
1058
+ // firstChildRef is contained by the fragment
1059
+ expectPosition (
1060
+ fragmentRef . current . compareDocumentPosition ( firstChildRef . current ) ,
1061
+ {
1062
+ preceding : false ,
1063
+ following : false ,
1064
+ contains : false ,
1065
+ containedBy : true ,
1066
+ disconnected : false ,
1067
+ implementationSpecific : false ,
1068
+ } ,
1069
+ ) ;
1070
+
1071
+ // middleChildRef is contained by the fragment
1072
+ expectPosition (
1073
+ fragmentRef . current . compareDocumentPosition ( middleChildRef . current ) ,
1074
+ {
1075
+ preceding : false ,
1076
+ following : false ,
1077
+ contains : false ,
1078
+ containedBy : true ,
1079
+ disconnected : false ,
1080
+ implementationSpecific : false ,
1081
+ } ,
1082
+ ) ;
1083
+
1084
+ // lastChildRef is contained by the fragment
1085
+ expectPosition (
1086
+ fragmentRef . current . compareDocumentPosition ( lastChildRef . current ) ,
1087
+ {
1088
+ preceding : false ,
1089
+ following : false ,
1090
+ contains : false ,
1091
+ containedBy : true ,
1092
+ disconnected : false ,
1093
+ implementationSpecific : false ,
1094
+ } ,
1095
+ ) ;
1096
+
1097
+ // containerRef preceds and contains the fragment
1098
+ expectPosition (
1099
+ fragmentRef . current . compareDocumentPosition ( containerRef . current ) ,
1100
+ {
1101
+ preceding : true ,
1102
+ following : false ,
1103
+ contains : true ,
1104
+ containedBy : false ,
1105
+ disconnected : false ,
1106
+ implementationSpecific : false ,
1107
+ } ,
1108
+ ) ;
1109
+
1110
+ expectPosition (
1111
+ fragmentRef . current . compareDocumentPosition ( disconnectedElement ) ,
1112
+ {
1113
+ preceding : false ,
1114
+ following : true ,
1115
+ contains : false ,
1116
+ containedBy : false ,
1117
+ disconnected : true ,
1118
+ implementationSpecific : true ,
1119
+ } ,
1120
+ ) ;
1121
+ } ) ;
1122
+
1123
+ // @gate enableFragmentRefs
1124
+ it ( 'handles fragment instances with one child' , async ( ) => {
1125
+ const fragmentRef = React . createRef ( ) ;
1126
+ const beforeRef = React . createRef ( ) ;
1127
+ const afterRef = React . createRef ( ) ;
1128
+ const containerRef = React . createRef ( ) ;
1129
+ const onlyChildRef = React . createRef ( ) ;
1130
+ const disconnectedElement = document . createElement ( 'div' ) ;
1131
+ const root = ReactDOMClient . createRoot ( container ) ;
1132
+
1133
+ function Test ( ) {
1134
+ return (
1135
+ < div ref = { containerRef } >
1136
+ < div ref = { beforeRef } />
1137
+ < React . Fragment ref = { fragmentRef } >
1138
+ < div ref = { onlyChildRef } />
1139
+ </ React . Fragment >
1140
+ < div ref = { afterRef } />
1141
+ </ div >
1142
+ ) ;
1143
+ }
1144
+
1145
+ await act ( ( ) => root . render ( < Test /> ) ) ;
1146
+ expectPosition (
1147
+ fragmentRef . current . compareDocumentPosition ( beforeRef . current ) ,
1148
+ {
1149
+ preceding : true ,
1150
+ following : false ,
1151
+ contains : false ,
1152
+ containedBy : false ,
1153
+ disconnected : false ,
1154
+ implementationSpecific : false ,
1155
+ } ,
1156
+ ) ;
1157
+ expectPosition (
1158
+ fragmentRef . current . compareDocumentPosition ( afterRef . current ) ,
1159
+ {
1160
+ preceding : false ,
1161
+ following : true ,
1162
+ contains : false ,
1163
+ containedBy : false ,
1164
+ disconnected : false ,
1165
+ implementationSpecific : false ,
1166
+ } ,
1167
+ ) ;
1168
+ expectPosition (
1169
+ fragmentRef . current . compareDocumentPosition ( onlyChildRef . current ) ,
1170
+ {
1171
+ preceding : false ,
1172
+ following : false ,
1173
+ contains : false ,
1174
+ containedBy : true ,
1175
+ disconnected : false ,
1176
+ implementationSpecific : false ,
1177
+ } ,
1178
+ ) ;
1179
+ expectPosition (
1180
+ fragmentRef . current . compareDocumentPosition ( containerRef . current ) ,
1181
+ {
1182
+ preceding : true ,
1183
+ following : false ,
1184
+ contains : true ,
1185
+ containedBy : false ,
1186
+ disconnected : false ,
1187
+ implementationSpecific : false ,
1188
+ } ,
1189
+ ) ;
1190
+ expectPosition (
1191
+ fragmentRef . current . compareDocumentPosition ( disconnectedElement ) ,
1192
+ {
1193
+ preceding : false ,
1194
+ following : true ,
1195
+ contains : false ,
1196
+ containedBy : false ,
1197
+ disconnected : true ,
1198
+ implementationSpecific : true ,
1199
+ } ,
1200
+ ) ;
1201
+ } ) ;
1202
+
1203
+ // @gate enableFragmentRefs
1204
+ it ( 'returns disconnected and implementation specific for any comparison with empty fragment instances' , async ( ) => {
1205
+ const fragmentRef = React . createRef ( ) ;
1206
+ const beforeRef = React . createRef ( ) ;
1207
+ const afterRef = React . createRef ( ) ;
1208
+ const containerRef = React . createRef ( ) ;
1209
+ const root = ReactDOMClient . createRoot ( container ) ;
1210
+
1211
+ function Test ( ) {
1212
+ return (
1213
+ < div ref = { containerRef } >
1214
+ < div ref = { beforeRef } />
1215
+ < React . Fragment ref = { fragmentRef } />
1216
+ < div ref = { afterRef } />
1217
+ </ div >
1218
+ ) ;
1219
+ }
1220
+
1221
+ await act ( ( ) => root . render ( < Test /> ) ) ;
1222
+
1223
+ expectPosition (
1224
+ fragmentRef . current . compareDocumentPosition ( document . body ) ,
1225
+ {
1226
+ preceding : false ,
1227
+ following : false ,
1228
+ contains : false ,
1229
+ containedBy : false ,
1230
+ disconnected : true ,
1231
+ implementationSpecific : true ,
1232
+ } ,
1233
+ ) ;
1234
+ expectPosition (
1235
+ fragmentRef . current . compareDocumentPosition ( beforeRef . current ) ,
1236
+ {
1237
+ preceding : false ,
1238
+ following : false ,
1239
+ contains : false ,
1240
+ containedBy : false ,
1241
+ disconnected : true ,
1242
+ implementationSpecific : true ,
1243
+ } ,
1244
+ ) ;
1245
+ expectPosition (
1246
+ fragmentRef . current . compareDocumentPosition ( afterRef . current ) ,
1247
+ {
1248
+ preceding : false ,
1249
+ following : false ,
1250
+ contains : false ,
1251
+ containedBy : false ,
1252
+ disconnected : true ,
1253
+ implementationSpecific : true ,
1254
+ } ,
1255
+ ) ;
1256
+ expectPosition (
1257
+ fragmentRef . current . compareDocumentPosition ( containerRef . current ) ,
1258
+ {
1259
+ preceding : false ,
1260
+ following : false ,
1261
+ contains : false ,
1262
+ containedBy : false ,
1263
+ disconnected : true ,
1264
+ implementationSpecific : true ,
1265
+ } ,
1266
+ ) ;
1267
+ } ) ;
1268
+ } ) ;
969
1269
} ) ;
0 commit comments