@@ -1196,4 +1196,144 @@ TEST_F(
11961196 EXPECT_CALL (*localConnections_[1 ], disconnect ()).RetiresOnSaturation ();
11971197 getInspectorInstance ().removePage (pageId);
11981198}
1199+
1200+ TEST_F (InspectorPackagerConnectionTest, TestRejectedPageConnection) {
1201+ // Configure gmock to expect calls in a specific order.
1202+ InSequence mockCallsMustBeInSequence;
1203+
1204+ enum {
1205+ Accept,
1206+ RejectSilently,
1207+ RejectWithDisconnect
1208+ } mockNextConnectionBehavior;
1209+
1210+ auto pageId = getInspectorInstance ().addPage (
1211+ " mock-title" ,
1212+ " mock-vm" ,
1213+ [&mockNextConnectionBehavior,
1214+ this ](auto remoteConnection) -> std::unique_ptr<ILocalConnection> {
1215+ switch (mockNextConnectionBehavior) {
1216+ case Accept:
1217+ return localConnections_.make_unique (std::move (remoteConnection));
1218+ case RejectSilently:
1219+ return nullptr ;
1220+ case RejectWithDisconnect:
1221+ remoteConnection->onDisconnect ();
1222+ return nullptr ;
1223+ }
1224+ });
1225+
1226+ packagerConnection_->connect ();
1227+
1228+ ASSERT_TRUE (webSockets_[0 ]);
1229+
1230+ // Reject the connection by returning nullptr.
1231+ mockNextConnectionBehavior = RejectSilently;
1232+
1233+ EXPECT_CALL (
1234+ *webSockets_[0 ],
1235+ send (JsonParsed (AllOf (
1236+ AtJsonPtr (" /event" , Eq (" disconnect" )),
1237+ AtJsonPtr (" /payload/pageId" , Eq (std::to_string (pageId)))))))
1238+ .RetiresOnSaturation ();
1239+
1240+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1241+ R"( {{
1242+ "event": "connect",
1243+ "payload": {{
1244+ "pageId": {0}
1245+ }}
1246+ }})" ,
1247+ toJson (std::to_string (pageId))));
1248+
1249+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1250+ R"( {{
1251+ "event": "wrappedEvent",
1252+ "payload": {{
1253+ "pageId": {0},
1254+ "wrappedEvent": {1}
1255+ }}
1256+ }})" ,
1257+ toJson (std::to_string (pageId)),
1258+ toJson (R"( {
1259+ "method": "FakeDomain.fakeMethod",
1260+ "id": 1,
1261+ "params": ["arg1", "arg2"]
1262+ })" )));
1263+
1264+ // Reject the connection by explicitly calling onDisconnect(), then returning
1265+ // nullptr.
1266+ mockNextConnectionBehavior = RejectWithDisconnect;
1267+
1268+ EXPECT_CALL (
1269+ *webSockets_[0 ],
1270+ send (JsonParsed (AllOf (
1271+ AtJsonPtr (" /event" , Eq (" disconnect" )),
1272+ AtJsonPtr (" /payload/pageId" , Eq (std::to_string (pageId)))))))
1273+ .RetiresOnSaturation ();
1274+
1275+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1276+ R"( {{
1277+ "event": "connect",
1278+ "payload": {{
1279+ "pageId": {0}
1280+ }}
1281+ }})" ,
1282+ toJson (std::to_string (pageId))));
1283+
1284+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1285+ R"( {{
1286+ "event": "wrappedEvent",
1287+ "payload": {{
1288+ "pageId": {0},
1289+ "wrappedEvent": {1}
1290+ }}
1291+ }})" ,
1292+ toJson (std::to_string (pageId)),
1293+ toJson (R"( {
1294+ "method": "FakeDomain.fakeMethod",
1295+ "id": 2,
1296+ "params": ["arg1", "arg2"]
1297+ })" )));
1298+
1299+ // Accept a connection after previously rejecting connections to the same
1300+ // page.
1301+ mockNextConnectionBehavior = Accept;
1302+
1303+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1304+ R"( {{
1305+ "event": "connect",
1306+ "payload": {{
1307+ "pageId": {0}
1308+ }}
1309+ }})" ,
1310+ toJson (std::to_string (pageId))));
1311+
1312+ EXPECT_CALL (
1313+ *localConnections_[0 ],
1314+ sendMessage (JsonParsed (AllOf (
1315+ AtJsonPtr (" /method" , Eq (" FakeDomain.fakeMethod" )),
1316+ AtJsonPtr (" /id" , Eq (3 )),
1317+ AtJsonPtr (" /params" , ElementsAre (" arg1" , " arg2" ))))))
1318+ .RetiresOnSaturation ();
1319+
1320+ webSockets_[0 ]->getDelegate ().didReceiveMessage (sformat (
1321+ R"( {{
1322+ "event": "wrappedEvent",
1323+ "payload": {{
1324+ "pageId": {0},
1325+ "wrappedEvent": {1}
1326+ }}
1327+ }})" ,
1328+ toJson (std::to_string (pageId)),
1329+ toJson (R"( {
1330+ "method": "FakeDomain.fakeMethod",
1331+ "id": 3,
1332+ "params": ["arg1", "arg2"]
1333+ })" )));
1334+
1335+ EXPECT_CALL (*localConnections_[0 ], disconnect ()).RetiresOnSaturation ();
1336+ getInspectorInstance ().removePage (pageId);
1337+ }
1338+
11991339} // namespace facebook::react::jsinspector_modern
0 commit comments