@@ -1004,6 +1004,162 @@ describe('ReactDOMServerHooks', () => {
1004
1004
) ;
1005
1005
} ) ;
1006
1006
1007
+ it ( 'useOpaqueIdentifier identifierPrefix works for server renderer and does not clash' , async ( ) => {
1008
+ function ChildTwo ( { id} ) {
1009
+ return < div id = { id } > Child Three</ div > ;
1010
+ }
1011
+ function App ( ) {
1012
+ const id = useOpaqueIdentifier ( ) ;
1013
+ const idTwo = useOpaqueIdentifier ( ) ;
1014
+
1015
+ return (
1016
+ < div >
1017
+ < div aria-labelledby = { id } > Chid One</ div >
1018
+ < ChildTwo id = { id } />
1019
+ < div aria-labelledby = { idTwo } > Child Three</ div >
1020
+ < div id = { idTwo } > Child Four</ div >
1021
+ </ div >
1022
+ ) ;
1023
+ }
1024
+
1025
+ const containerOne = document . createElement ( 'div' ) ;
1026
+ document . body . append ( containerOne ) ;
1027
+
1028
+ containerOne . innerHTML = ReactDOMServer . renderToString ( < App /> , {
1029
+ identifierPrefix : 'one' ,
1030
+ } ) ;
1031
+
1032
+ const containerTwo = document . createElement ( 'div' ) ;
1033
+ document . body . append ( containerTwo ) ;
1034
+
1035
+ containerTwo . innerHTML = ReactDOMServer . renderToString ( < App /> , {
1036
+ identifierPrefix : 'two' ,
1037
+ } ) ;
1038
+
1039
+ expect ( document . body . children . length ) . toEqual ( 2 ) ;
1040
+ const childOne = document . body . children [ 0 ] ;
1041
+ const childTwo = document . body . children [ 1 ] ;
1042
+
1043
+ expect (
1044
+ childOne . children [ 0 ] . children [ 0 ] . getAttribute ( 'aria-labelledby' ) ,
1045
+ ) . toEqual ( childOne . children [ 0 ] . children [ 1 ] . getAttribute ( 'id' ) ) ;
1046
+ expect (
1047
+ childOne . children [ 0 ] . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1048
+ ) . toEqual ( childOne . children [ 0 ] . children [ 3 ] . getAttribute ( 'id' ) ) ;
1049
+
1050
+ expect (
1051
+ childOne . children [ 0 ] . children [ 0 ] . getAttribute ( 'aria-labelledby' ) ,
1052
+ ) . not . toEqual (
1053
+ childOne . children [ 0 ] . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1054
+ ) ;
1055
+
1056
+ expect (
1057
+ childOne . children [ 0 ] . children [ 0 ]
1058
+ . getAttribute ( 'aria-labelledby' )
1059
+ . startsWith ( 'one' ) ,
1060
+ ) . toBe ( true ) ;
1061
+ expect (
1062
+ childOne . children [ 0 ] . children [ 2 ]
1063
+ . getAttribute ( 'aria-labelledby' )
1064
+ . includes ( 'one' ) ,
1065
+ ) . toBe ( true ) ;
1066
+
1067
+ expect (
1068
+ childTwo . children [ 0 ] . children [ 0 ] . getAttribute ( 'aria-labelledby' ) ,
1069
+ ) . toEqual ( childTwo . children [ 0 ] . children [ 1 ] . getAttribute ( 'id' ) ) ;
1070
+ expect (
1071
+ childTwo . children [ 0 ] . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1072
+ ) . toEqual ( childTwo . children [ 0 ] . children [ 3 ] . getAttribute ( 'id' ) ) ;
1073
+
1074
+ expect (
1075
+ childTwo . children [ 0 ] . children [ 0 ] . getAttribute ( 'aria-labelledby' ) ,
1076
+ ) . not . toEqual (
1077
+ childTwo . children [ 0 ] . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1078
+ ) ;
1079
+
1080
+ expect (
1081
+ childTwo . children [ 0 ] . children [ 0 ]
1082
+ . getAttribute ( 'aria-labelledby' )
1083
+ . startsWith ( 'two' ) ,
1084
+ ) . toBe ( true ) ;
1085
+ expect (
1086
+ childTwo . children [ 0 ] . children [ 2 ]
1087
+ . getAttribute ( 'aria-labelledby' )
1088
+ . startsWith ( 'two' ) ,
1089
+ ) . toBe ( true ) ;
1090
+ } ) ;
1091
+
1092
+ it ( 'useOpaqueIdentifier identifierPrefix works for multiple reads on a streaming server renderer' , async ( ) => {
1093
+ function ChildTwo ( ) {
1094
+ const id = useOpaqueIdentifier ( ) ;
1095
+
1096
+ return < div id = { id } > Child Two</ div > ;
1097
+ }
1098
+
1099
+ function App ( ) {
1100
+ const id = useOpaqueIdentifier ( ) ;
1101
+
1102
+ return (
1103
+ < >
1104
+ < div id = { id } > Child One</ div >
1105
+ < ChildTwo />
1106
+ < div aria-labelledby = { id } > Aria One</ div >
1107
+ </ >
1108
+ ) ;
1109
+ }
1110
+
1111
+ const container = document . createElement ( 'div' ) ;
1112
+ document . body . append ( container ) ;
1113
+
1114
+ const streamOne = ReactDOMServer . renderToNodeStream ( < App /> , {
1115
+ identifierPrefix : 'one' ,
1116
+ } ) . setEncoding ( 'utf8' ) ;
1117
+ const streamTwo = ReactDOMServer . renderToNodeStream ( < App /> , {
1118
+ identifierPrefix : 'two' ,
1119
+ } ) . setEncoding ( 'utf8' ) ;
1120
+
1121
+ const containerOne = document . createElement ( 'div' ) ;
1122
+ const containerTwo = document . createElement ( 'div' ) ;
1123
+
1124
+ streamOne . _read ( 10 ) ;
1125
+ streamTwo . _read ( 10 ) ;
1126
+
1127
+ containerOne . innerHTML = streamOne . read ( ) ;
1128
+ containerTwo . innerHTML = streamTwo . read ( ) ;
1129
+
1130
+ expect ( containerOne . children [ 0 ] . getAttribute ( 'id' ) ) . not . toEqual (
1131
+ containerOne . children [ 1 ] . getAttribute ( 'id' ) ,
1132
+ ) ;
1133
+ expect ( containerTwo . children [ 0 ] . getAttribute ( 'id' ) ) . not . toEqual (
1134
+ containerTwo . children [ 1 ] . getAttribute ( 'id' ) ,
1135
+ ) ;
1136
+ expect ( containerOne . children [ 0 ] . getAttribute ( 'id' ) ) . not . toEqual (
1137
+ containerTwo . children [ 0 ] . getAttribute ( 'id' ) ,
1138
+ ) ;
1139
+ expect (
1140
+ containerOne . children [ 0 ] . getAttribute ( 'id' ) . includes ( 'one' ) ,
1141
+ ) . toBe ( true ) ;
1142
+ expect (
1143
+ containerOne . children [ 1 ] . getAttribute ( 'id' ) . includes ( 'one' ) ,
1144
+ ) . toBe ( true ) ;
1145
+ expect (
1146
+ containerTwo . children [ 0 ] . getAttribute ( 'id' ) . includes ( 'two' ) ,
1147
+ ) . toBe ( true ) ;
1148
+ expect (
1149
+ containerTwo . children [ 1 ] . getAttribute ( 'id' ) . includes ( 'two' ) ,
1150
+ ) . toBe ( true ) ;
1151
+
1152
+ expect ( containerOne . children [ 1 ] . getAttribute ( 'id' ) ) . not . toEqual (
1153
+ containerTwo . children [ 1 ] . getAttribute ( 'id' ) ,
1154
+ ) ;
1155
+ expect ( containerOne . children [ 0 ] . getAttribute ( 'id' ) ) . toEqual (
1156
+ containerOne . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1157
+ ) ;
1158
+ expect ( containerTwo . children [ 0 ] . getAttribute ( 'id' ) ) . toEqual (
1159
+ containerTwo . children [ 2 ] . getAttribute ( 'aria-labelledby' ) ,
1160
+ ) ;
1161
+ } ) ;
1162
+
1007
1163
it ( 'useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered' , async ( ) => {
1008
1164
let _setShowDiv ;
1009
1165
function App ( ) {
0 commit comments