示例#1
0
        public void UpdatedFieldIsAdded_CanBeRetrieved()
        {
            var path = new GraphFieldPath(GraphCollection.Subscription, "path1/path2");
            var mock = new Mock <IGraphField>();

            mock.Setup(x => x.Route).Returns(path);
            mock.Setup(x => x.FieldSource).Returns(GraphFieldTemplateSource.Action);

            var o  = new object();
            var o1 = new object();

            var collection = new DefaultFieldSourceCollection(GraphFieldTemplateSource.Action);

            // add then update the source
            collection.AddSource(mock.Object, o);
            collection.AddSource(mock.Object, o1);

            var found = collection.TryRetrieveSource(mock.Object, out var result);

            Assert.IsTrue(collection.ContainsKey(mock.Object));
            Assert.AreEqual(1, collection.Count);

            Assert.IsTrue(found);
            Assert.IsNotNull(result);

            // ensure retrieved result is the second object added
            Assert.AreEqual(o1, result);
        }
示例#2
0
        /// <summary>
        /// Makes the unique route being used for this virtual field type safe, removing special control characters
        /// but retaining its uniqueness.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns>System.String.</returns>
        private string MakeSafeTypeNameFromRoutePath(GraphFieldPath path)
        {
            var segments = new List <string>();

            foreach (var pathSegmentName in path)
            {
                switch (pathSegmentName)
                {
                case Constants.Routing.QUERY_ROOT:
                    segments.Add(Constants.ReservedNames.QUERY_TYPE_NAME);
                    break;

                case Constants.Routing.MUTATION_ROOT:
                    segments.Add(Constants.ReservedNames.MUTATION_TYPE_NAME);
                    break;

                case Constants.Routing.SUBSCRIPTION_ROOT:
                    segments.Add(Constants.ReservedNames.SUBSCRIPTION_TYPE_NAME);
                    break;

                default:
                    segments.Add(_formatter.FormatGraphTypeName(pathSegmentName));
                    break;
                }
            }

            segments.Reverse();
            return(string.Join("_", segments));
        }
示例#3
0
        public void Destructuring(
            string rawPath,
            string expectedPath,
            bool expectedValidState,
            GraphCollection expectedRoot,
            string expectedName,
            bool shouldHaveParent,
            string expectedParentPath)
        {
            var route = new GraphFieldPath(rawPath);

            // valid path should be untouched
            Assert.AreEqual(expectedValidState, route.IsValid);
            Assert.AreEqual(rawPath, route.Raw);
            Assert.AreEqual(expectedPath, route.Path);
            Assert.AreEqual(expectedRoot, route.RootCollection);
            Assert.AreEqual(expectedName, route.Name);

            if (!shouldHaveParent)
            {
                Assert.IsNull(route.Parent);
            }
            else
            {
                Assert.IsNotNull(route.Parent);
                Assert.AreEqual(expectedParentPath, route.Parent.Path);
            }
        }
示例#4
0
        public void UnFoundField_IsNotReturned()
        {
            var path = new GraphFieldPath(GraphCollection.Subscription, "path1/path2");
            var mock = new Mock <IGraphField>();

            mock.Setup(x => x.Route).Returns(path);
            mock.Setup(x => x.FieldSource).Returns(GraphFieldTemplateSource.Action);

            var path1 = new GraphFieldPath(GraphCollection.Subscription, "path1/path3");
            var mock1 = new Mock <IGraphField>();

            mock1.Setup(x => x.Route).Returns(path1);
            mock1.Setup(x => x.FieldSource).Returns(GraphFieldTemplateSource.Action);

            var o          = new object();
            var collection = new DefaultFieldSourceCollection();

            collection.AddSource(mock.Object, o);
            Assert.AreEqual(1, collection.Count);

            // retreive for an object def. not in the collection
            var found = collection.TryRetrieveSource(mock1.Object, out var result);

            Assert.IsFalse(found);
            Assert.IsNull(result);
        }
        public async Task ReceiveEvent_OnNonSubscribedEventNAme_YieldsNothing()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            // start a real subscription so the client is tracking one
            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "subscription {  apolloSubscription { watchForPropObject { property1 } } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            // fire an event against a route not tracked, ensure the client skips it.
            var route = new GraphFieldPath("[subscription]/ApolloSubscription/WatchForPropObject_NotReal");
            await apolloClient.ReceiveEvent(route, new TwoPropertyObject()
            {
                Property1 = "value1",
                Property2 = 33,
            });

            Assert.AreEqual(0, socketClient.ResponseMessageCount);
        }
        public async Task ReceiveEvent_OnStartedSubscription_YieldsDataMessage()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            var startMessage = new ApolloClientStartMessage()
            {
                Id      = "abc",
                Payload = new GraphQueryData()
                {
                    Query = "subscription {  apolloSubscription { watchForPropObject { property1 } } }",
                },
            };

            await apolloClient.DispatchMessage(startMessage);

            var route = new GraphFieldPath("[subscription]/ApolloSubscription/WatchForPropObject");
            await apolloClient.ReceiveEvent(route, new TwoPropertyObject()
            {
                Property1 = "value1",
                Property2 = 33,
            });

            socketClient.AssertApolloResponse(
                ApolloMessageType.DATA,
                "abc",
                @"{
                    ""data"" : {
                        ""apolloSubscription"" : {
                            ""watchForPropObject"" : {
                                ""property1"" : ""value1"",
                            }
                        }
                    }
                }");
        }
示例#7
0
        public void GraphRouteArgumentPath_YieldsAlternatePathString()
        {
            var parent = new GraphFieldPath($"{Constants.Routing.TYPE_ROOT}/typeName/fieldName");
            var route  = new GraphArgumentFieldPath(parent, "arg1");

            Assert.AreEqual($"{Constants.Routing.TYPE_ROOT}/typeName/fieldName[arg1]", route.Path);
        }
        public void ApolloClientSubscriptionEventReceived_PropertyCheck()
        {
            var router = new Mock <ISubscriptionEventRouter>();
            var server = new ApolloSubscriptionServer <GraphSchema>(
                new GraphSchema(),
                new SubscriptionServerOptions <GraphSchema>(),
                router.Object);

            var connection = new Mock <IClientConnection>();
            var proxy      = new ApolloClientProxy <GraphSchema>(
                connection.Object,
                new SubscriptionServerOptions <GraphSchema>(),
                new AspNet.Apollo.Messages.Converters.ApolloMessageConverterFactory());

            var sub = new Mock <ISubscription>();

            sub.Setup(x => x.Id).Returns("sub1");

            var subs = new List <ISubscription>();

            subs.Add(sub.Object);

            var fieldPath = new GraphFieldPath("[subscription]/bob1");

            var entry = new ApolloClientSubscriptionEventReceived <GraphSchema>(
                proxy,
                fieldPath,
                subs);

            Assert.AreEqual(proxy.Id, entry.ClientId);
            Assert.AreEqual(fieldPath.ToString(), entry.SubscriptionRoute);
            Assert.AreEqual(1, entry.SubscriptionCount);
            CollectionAssert.AreEquivalent(subs.Select(x => x.Id).ToList(), entry.SubscriptionIds);
            Assert.AreNotEqual(entry.GetType().Name, entry.ToString());
        }
示例#9
0
        public void Join_WithRoot_JoinsAsExpected(GraphCollection root, string leftSide, string rightSide, string expectedOutput)
        {
            // standard join
            var fragment = GraphFieldPath.Join(root, leftSide, rightSide);

            Assert.AreEqual(expectedOutput, fragment);
        }
示例#10
0
        private GraphFieldArgumentTemplate ExtractParameterTemplate(string paramName, out ParameterInfo paramInfo)
        {
            paramInfo = typeof(ParameterTestClass)
                        .GetMethod(nameof(ParameterTestClass.TestMethod))
                        .GetParameters()
                        .FirstOrDefault(x => x.Name == paramName);

            var mockMethod = new Mock <IGraphFieldBaseTemplate>();

            mockMethod.Setup(x => x.InternalFullName)
            .Returns($"{nameof(ParameterTestClass)}.{nameof(ParameterTestClass.TestMethod)}");
            mockMethod.Setup(x => x.ObjectType).Returns(typeof(ParameterTestClass));

            var route = new GraphFieldPath(GraphFieldPath.Join(
                                               GraphCollection.Query,
                                               nameof(ParameterTestClass),
                                               nameof(ParameterTestClass.TestMethod)));

            mockMethod.Setup(x => x.Route).Returns(route);

            var argTemplate = new GraphFieldArgumentTemplate(mockMethod.Object, paramInfo);

            argTemplate.Parse();
            argTemplate.ValidateOrThrow();

            return(argTemplate);
        }
示例#11
0
        public void IsSameRoute(string fragment1, string fragment2, bool areTheSame)
        {
            var route1 = new GraphFieldPath(fragment1);
            var route2 = new GraphFieldPath(fragment2);

            // valid path should be untouched
            Assert.AreEqual(areTheSame, route1.IsSameRoute(route2));
        }
示例#12
0
        public void HasChildRoute(string fragment1, string fragment2, bool frag2IsChildof1)
        {
            var route  = new GraphFieldPath(fragment1);
            var route2 = new GraphFieldPath(fragment2);

            // route2 is a child of route 1, but not the other way around
            Assert.AreEqual(frag2IsChildof1, route.HasChildRoute(route2));
        }
        /// <summary>
        /// When overridden in a child class, this metyhod builds the route that will be assigned to this method
        /// using the implementation rules of the concrete type.
        /// </summary>
        /// <returns>GraphRoutePath.</returns>
        protected override GraphFieldPath GenerateFieldPath()
        {
            // a standard graph object cannot contain any route pathing or nesting like controllers can
            // before creating hte route, ensure that the declared name, by itself, is valid for graphql
            var graphName = GraphTypeNames.ParseName(this.ObjectType, TypeKind.INPUT_OBJECT);

            return(new GraphFieldPath(GraphFieldPath.Join(GraphCollection.Types, graphName)));
        }
示例#14
0
        /// <summary>
        /// When overridden in a child class, this method builds the route that will be assigned to this method
        /// using the implementation rules of the concrete type.
        /// </summary>
        /// <returns>GraphRoutePath.</returns>
        protected override GraphFieldPath GenerateFieldPath()
        {
            // A class property cannot contain any route pathing or nesting like controllers or actions.
            // Before creating hte route, ensure that the declared name, by itself, is valid for graphql such that resultant
            // global path for this property will also be correct.
            var graphName = this.SingleAttributeOfTypeOrDefault <GraphFieldAttribute>()?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME;

            graphName = graphName.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Property.Name).Trim();

            return(new GraphFieldPath(GraphFieldPath.Join(this.Parent.Route.Path, graphName)));
        }
        /// <summary>
        /// When overridden in a child class, this metyhod builds the route that will be assigned to this method
        /// using the implementation rules of the concrete type.
        /// </summary>
        /// <returns>GraphRoutePath.</returns>
        protected override GraphFieldPath GenerateFieldPath()
        {
            // an object method cannot contain any route pathing or nesting like controller methods can
            // before creating hte route, ensure that the declared name, by itself, is valid for graphql
            var graphName = this.Method.SingleAttributeOrDefault <GraphFieldAttribute>()?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME;

            graphName = graphName.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Method.Name).Trim();

            GraphValidation.EnsureGraphNameOrThrow(this.InternalFullName, graphName);
            return(new GraphFieldPath(GraphFieldPath.Join(this.Parent.Route.Path, graphName)));
        }
示例#16
0
        public void GenerateParentPathSegments_TopLevelFieldReturnsEmptyList()
        {
            var fragment = "[query]/path1";
            var route    = new GraphFieldPath(fragment);

            Assert.IsTrue(route.IsTopLevelField);

            var parents = route.GenerateParentPathSegments();

            Assert.IsNotNull(parents);
            Assert.AreEqual(0, parents.Count);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ApolloClientSubscriptionEventReceived{TSchema}" /> class.
 /// </summary>
 /// <param name="client">The client proxy that received the event.</param>
 /// <param name="fieldPath">The field path of the event recieved.</param>
 /// <param name="subscriptionsToReceive">The filtered set of subscriptions for this client
 /// that will receive the event.</param>
 public ApolloClientSubscriptionEventReceived(
     ApolloClientProxy <TSchema> client,
     GraphFieldPath fieldPath,
     IReadOnlyList <ISubscription> subscriptionsToReceive)
     : base(ApolloLogEventIds.ClientSubscriptionEventRecieved)
 {
     this.SchemaTypeName    = typeof(TSchema).FriendlyName(true);
     this.SubscriptionRoute = fieldPath.Path;
     this.SubscriptionCount = subscriptionsToReceive.Count;
     this.SubscriptionIds   = subscriptionsToReceive.Select(x => x.Id).ToList();
     this.ClientId          = client.Id;
 }
示例#18
0
        public void GenerateParentPathSegments_InvalidPathSegmentReturnsEmptyList()
        {
            var fragment = "pat!$#@%h1";
            var route    = new GraphFieldPath(fragment);

            Assert.IsFalse(route.IsValid);

            var parents = route.GenerateParentPathSegments();

            Assert.IsNotNull(parents);
            Assert.AreEqual(0, parents.Count);
        }
示例#19
0
        /// <summary>
        /// When overridden in a child class, this method builds the route that will be assigned to this method
        /// using the implementation rules of the concrete type.
        /// </summary>
        /// <returns>GraphRoutePath.</returns>
        protected override GraphFieldPath GenerateFieldPath()
        {
            // extract the parent name from the global meta data about the type being extended
            var parentName = GraphTypeNames.ParseName(_typeAttrib.TypeToExtend, TypeKind.OBJECT);

            // an object method cannot contain any route pathing or nesting like controller methods can
            // before creating hte route, ensure that the declared name, by itself, is valid for graphql
            var graphName = _typeAttrib.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME;

            graphName = graphName.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Method.Name).Trim();

            return(new GraphFieldPath(GraphFieldPath.Join(GraphCollection.Types, parentName, graphName)));
        }
        public async Task ReceiveEvent_WhenNoSubscriptions_YieldsNothing()
        {
            (var socketClient, var apolloClient) = await this.CreateConnection();

            var route = new GraphFieldPath("[subscription]/ApolloSubscription/WatchForPropObject");
            await apolloClient.ReceiveEvent(route, new TwoPropertyObject()
            {
                Property1 = "value1",
                Property2 = 33,
            });

            Assert.AreEqual(0, socketClient.ResponseMessageCount);
        }
        public void AddNewSub_NotReturnedOnNullRoute()
        {
            var collection = new ApolloSubscriptionCollection <GraphSchema>();

            var fakeSub = new Mock <ISubscription <GraphSchema> >();

            var field = new GraphFieldPath("[subscription]/field1");

            fakeSub.Setup(x => x.Id).Returns("abc123");
            fakeSub.Setup(x => x.Route).Returns(field);

            collection.Add(fakeSub.Object);
            Assert.AreEqual(0, collection.CountByRoute(null));
        }
示例#22
0
        public void GenerateParentPathSegments_LeafPathReturnsParentList()
        {
            var fragment = "[query]/path1/path2/path3/path4";
            var route    = new GraphFieldPath(fragment);

            var parents = route.GenerateParentPathSegments();

            Assert.IsNotNull(parents);
            Assert.AreEqual(3, parents.Count);

            Assert.AreEqual("[query]/path1", parents[0].Path);
            Assert.AreEqual("[query]/path1/path2", parents[1].Path);
            Assert.AreEqual("[query]/path1/path2/path3", parents[2].Path);
        }
示例#23
0
        public void Destructuring_Query_TwoFragmentPathHasADefinedParent()
        {
            var fragment = "[query]/path1/path2";
            var route    = new GraphFieldPath(fragment);

            // valid path should be untouched
            Assert.IsTrue(route.IsValid);
            Assert.AreEqual(fragment, route.Raw);
            Assert.AreEqual(fragment, route.Path);
            Assert.IsNotNull(route.Parent);
            Assert.AreEqual(GraphCollection.Query, route.RootCollection);
            Assert.AreEqual("path2", route.Name);
            Assert.AreEqual("path1", route.Parent.Name);
            Assert.AreEqual("[query]/path1", route.Parent.Path);
        }
        /// <summary>
        /// When overridden in a child class, this metyhod builds the route that will be assigned to this method
        /// using the implementation rules of the concrete type.
        /// </summary>
        /// <returns>GraphRoutePath.</returns>
        protected override GraphFieldPath GenerateFieldPath()
        {
            // Various meta data fields about the method
            // -------------------------------------------
            var graphMethodAttrib = this.SingleAttributeOfTypeOrDefault <GraphFieldAttribute>();
            var fieldType         = graphMethodAttrib?.FieldType ?? GraphCollection.Unknown;

            var routeFragment = graphMethodAttrib?.Template?.Trim() ?? Constants.Routing.ACTION_METHOD_META_NAME;

            routeFragment = routeFragment.Replace(Constants.Routing.ACTION_METHOD_META_NAME, this.Method.Name).Trim();

            // remove the parent fragment this method should be nested under if this method is marked as a root entry
            var parentRouteFragment = (graphMethodAttrib?.IsRootFragment ?? false) ? string.Empty : this.Parent.Route.Path;

            return(new GraphFieldPath(GraphFieldPath.Join(fieldType, parentRouteFragment, routeFragment)));
        }
        /// <summary>
        /// Retrieves the total number of subscriptions registered for the given unique route.
        /// </summary>
        /// <param name="route">The route to filter by.</param>
        /// <returns>System.Int32.</returns>
        public int CountByRoute(GraphFieldPath route)
        {
            if (route == null || !route.IsValid)
            {
                return(0);
            }

            lock (_syncLock)
            {
                if (!_subsByRoute.ContainsKey(route))
                {
                    return(0);
                }

                return(_subsByRoute[route].Count);
            }
        }
        /// <summary>
        /// Finds the set all known subscriptions for a given route and returns them.
        /// </summary>
        /// <param name="route">The route.</param>
        /// <returns>IEnumerable&lt;ISubscription&lt;TSchema&gt;&gt;.</returns>
        public IReadOnlyList <ISubscription <TSchema> > RetreiveByRoute(GraphFieldPath route)
        {
            List <ISubscription <TSchema> > subs = new List <ISubscription <TSchema> >();

            if (route != null)
            {
                lock (_syncLock)
                {
                    if (_subsByRoute.ContainsKey(route))
                    {
                        subs.AddRange(_subsByRoute[route]);
                    }
                }
            }

            return(subs);
        }
示例#27
0
        public void NotADirectiveMethod_ThrowsException()
        {
            var method = typeof(TestDirectiveMethodTemplateContainer)
                         .GetMethod(nameof(TestDirectiveMethodTemplateContainer.NotADirectiveMethod));

            var mock = new Mock <IGraphTypeTemplate>();

            mock.Setup(x => x.InternalFullName).Returns("Simple");
            var route = new GraphFieldPath(GraphCollection.Directives, "Simple");

            mock.Setup(x => x.Route).Returns(route);
            var template = new GraphDirectiveMethodTemplate(mock.Object, method);

            Assert.Throws <GraphTypeDeclarationException>(() =>
            {
                template.ValidateOrThrow();
            });
        }
        private async Task ExecuteSubscriptionEvent(
            ISubscriptionClientProxy client,
            GraphFieldPath route,
            object data,
            CancellationToken cancelToken = default)
        {
            try
            {
                // execute the request through the runtime
                await _eventSendSemaphore.WaitAsync().ConfigureAwait(false);

                await client.ReceiveEvent(route, data, cancelToken).ConfigureAwait(false);
            }
            finally
            {
                _eventSendSemaphore.Release();
            }
        }
        public void AddNewSub_OfDifferentRoute_ReflectsInCollectionCount()
        {
            var collection = new ApolloSubscriptionCollection <GraphSchema>();

            var fakeSub = new Mock <ISubscription <GraphSchema> >();

            var field  = new GraphFieldPath("[subscription]/field1");
            var field2 = new GraphFieldPath("[subscription]/field2");
            var field3 = new GraphFieldPath("[subscription]/field3");

            fakeSub.Setup(x => x.Id).Returns("abc123");
            fakeSub.Setup(x => x.Route).Returns(field);

            var fakeSub2 = new Mock <ISubscription <GraphSchema> >();

            fakeSub2.Setup(x => x.Id).Returns("abc1234");
            fakeSub2.Setup(x => x.Route).Returns(field2);

            collection.Add(fakeSub.Object);
            collection.Add(fakeSub2.Object);
            Assert.AreEqual(1, collection.CountByRoute(field));
            Assert.AreEqual(1, collection.CountByRoute(field2));
            Assert.AreEqual(2, collection.Count);

            var foundSubs = collection.RetreiveByRoute(field);

            Assert.AreEqual(fakeSub.Object, foundSubs.Single());

            foundSubs = collection.RetreiveByRoute(field2);
            Assert.AreEqual(fakeSub2.Object, foundSubs.Single());

            foundSubs = collection.RetreiveByRoute(field3);
            CollectionAssert.IsEmpty(foundSubs);

            var counted = 0;

            foreach (var sub in collection)
            {
                Assert.IsTrue(sub == fakeSub.Object || sub == fakeSub2.Object);
                counted++;
            }

            Assert.AreEqual(2, counted);
        }
示例#30
0
        public void MethodWithSkipAttached_ThrowsException()
        {
            // afterfieldResolution is marked skipped
            var method = typeof(TestDirectiveMethodTemplateContainer)
                         .GetMethod(nameof(TestDirectiveMethodTemplateContainer.AfterFieldResolution));

            var mock = new Mock <IGraphTypeTemplate>();

            mock.Setup(x => x.InternalFullName).Returns("Simple");
            var route = new GraphFieldPath(GraphCollection.Directives, "Simple");

            mock.Setup(x => x.Route).Returns(route);
            var template = new GraphDirectiveMethodTemplate(mock.Object, method);

            Assert.Throws <GraphTypeDeclarationException>(() =>
            {
                template.ValidateOrThrow();
            });
        }