@@ -922,6 +922,117 @@ TEST_F(TodayServiceCase, SubscribeNodeChangeMismatchedId)
922
922
}
923
923
}
924
924
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
+
925
1036
TEST_F (TodayServiceCase, SubscribeNodeChangeMatchingVariable)
926
1037
{
927
1038
auto ast = peg::parseString (R"( subscription TestSubscription($taskId: ID!) {
0 commit comments