@@ -922,6 +922,117 @@ TEST_F(TodayServiceCase, SubscribeNodeChangeMismatchedId)
922922 }
923923}
924924
925+ TEST_F (TodayServiceCase, SubscribeNodeChangeFuzzyComparator)
926+ {
927+ auto ast = peg::parseString (R"( subscription TestSubscription {
928+ changedNode: nodeChange(id: "ZmFr") {
929+ changedId: id
930+ ...on Task {
931+ title
932+ isComplete
933+ }
934+ }
935+ })" );
936+ response::Value variables (response::Type::Map);
937+ auto state = std::make_shared<today::RequestState>(14 );
938+ bool filterCalled = false ;
939+ auto filterCallback = [&filterCalled](response::MapType::const_reference fuzzy) noexcept -> bool
940+ {
941+ EXPECT_FALSE (filterCalled);
942+ EXPECT_EQ (" id" , fuzzy.first ) << " should only get called once for the id argument" ;
943+ EXPECT_EQ (" ZmFr" , fuzzy.second .get <const response::StringType&>());
944+ filterCalled = true ;
945+ return true ;
946+ };
947+ auto subscriptionObject = std::make_shared<today::NodeChange>(
948+ [this ](const std::shared_ptr<service::RequestState>& state, std::vector<uint8_t >&& idArg) -> std::shared_ptr<service::Object>
949+ {
950+ const std::vector<uint8_t > fuzzyId { ' f' , ' a' , ' k' };
951+
952+ EXPECT_EQ (14 , std::static_pointer_cast<today::RequestState>(state)->requestId ) << " should pass the RequestState to the subscription resolvers" ;
953+ EXPECT_EQ (fuzzyId, idArg);
954+ return std::static_pointer_cast<service::Object>(std::make_shared<today::Task>(std::vector<uint8_t >(_fakeTaskId), " Don't forget" , true ));
955+ });
956+ response::Value result;
957+ auto key = _service->subscribe (service::SubscriptionParams { state, std::move (ast), " TestSubscription" , std::move (std::move (variables)) },
958+ [&result](std::future<response::Value> response)
959+ {
960+ result = response.get ();
961+ });
962+ _service->deliver (" nodeChange" , filterCallback, std::static_pointer_cast<service::Object>(subscriptionObject));
963+ _service->unsubscribe (key);
964+
965+ try
966+ {
967+ ASSERT_TRUE (filterCalled) << " should match the id parameter in the subscription" ;
968+ ASSERT_TRUE (result.type () == response::Type::Map);
969+ auto errorsItr = result.find (" errors" );
970+ if (errorsItr != result.get <const response::MapType&>().cend ())
971+ {
972+ FAIL () << response::toJSON (response::Value (errorsItr->second ));
973+ }
974+ const auto data = service::ScalarArgument::require (" data" , result);
975+
976+ const auto taskNode = service::ScalarArgument::require (" changedNode" , data);
977+ EXPECT_EQ (_fakeTaskId, service::IdArgument::require (" changedId" , taskNode)) << " id should match in base64 encoding" ;
978+ EXPECT_EQ (" Don't forget" , service::StringArgument::require (" title" , taskNode)) << " title should match" ;
979+ EXPECT_TRUE (service::BooleanArgument::require (" isComplete" , taskNode)) << " isComplete should match" ;
980+ }
981+ catch (const service::schema_exception& ex)
982+ {
983+ FAIL () << response::toJSON (response::Value (ex.getErrors ()));
984+ }
985+ }
986+
987+ TEST_F (TodayServiceCase, SubscribeNodeChangeFuzzyMismatch)
988+ {
989+ auto ast = peg::parseString (R"( subscription TestSubscription {
990+ changedNode: nodeChange(id: "ZmFrZVRhc2tJZA==") {
991+ changedId: id
992+ ...on Task {
993+ title
994+ isComplete
995+ }
996+ }
997+ })" );
998+ response::Value variables (response::Type::Map);
999+ bool filterCalled = false ;
1000+ auto filterCallback = [&filterCalled](response::MapType::const_reference fuzzy) noexcept -> bool
1001+ {
1002+ EXPECT_FALSE (filterCalled);
1003+ EXPECT_EQ (" id" , fuzzy.first ) << " should only get called once for the id argument" ;
1004+ EXPECT_EQ (" ZmFrZVRhc2tJZA==" , fuzzy.second .get <const response::StringType&>());
1005+ filterCalled = true ;
1006+ return false ;
1007+ };
1008+ bool calledResolver = false ;
1009+ auto subscriptionObject = std::make_shared<today::NodeChange>(
1010+ [this , &calledResolver](const std::shared_ptr<service::RequestState>& state, std::vector<uint8_t >&& idArg) -> std::shared_ptr<service::Object>
1011+ {
1012+ calledResolver = true ;
1013+ return nullptr ;
1014+ });
1015+ bool calledGet = false ;
1016+ auto key = _service->subscribe (service::SubscriptionParams { nullptr , std::move (ast), " TestSubscription" , std::move (std::move (variables)) },
1017+ [&calledGet](std::future<response::Value>)
1018+ {
1019+ calledGet = true ;
1020+ });
1021+ _service->deliver (" nodeChange" , filterCallback, std::static_pointer_cast<service::Object>(subscriptionObject));
1022+ _service->unsubscribe (key);
1023+
1024+ try
1025+ {
1026+ ASSERT_TRUE (filterCalled) << " should not match the id parameter in the subscription" ;
1027+ ASSERT_FALSE (calledResolver);
1028+ ASSERT_FALSE (calledGet);
1029+ }
1030+ catch (const service::schema_exception& ex)
1031+ {
1032+ FAIL () << response::toJSON (response::Value (ex.getErrors ()));
1033+ }
1034+ }
1035+
9251036TEST_F (TodayServiceCase, SubscribeNodeChangeMatchingVariable)
9261037{
9271038 auto ast = peg::parseString (R"( subscription TestSubscription($taskId: ID!) {
0 commit comments