Common options

Tanka provides SignalR hub and websockets server. Both of these use same underlying services for query execution.

Add required common services

Add services required for executing GraphQL queries, mutations and subscriptions. Main service added is IQueryStreamService which handles the plumping of execution.


        [Fact]
        public void AddTankaGraphQL()
        {
            /* When */
            Services.AddTankaGraphQL()
                .ConfigureSchema(() => default);

            /* Then */
            var provider = Services.BuildServiceProvider();

            // Options is added by the AddTankaGraphQL
            Assert.NotNull(provider.GetService<IOptions<ServerOptions>>());

            // Query stream service is added by AddTankaGraphQL
            Assert.NotNull(provider.GetService<IQueryStreamService>());
        }

Configure schema

Configure ISchema for execution by providing a factory function (can be async) used to get the schema for execution.

Simple without dependencies


        [Fact]
        public async Task Configure_Schema()
        {
            /* Given */
            var schema = Substitute.For<ISchema>();

            /* When */
            Services.AddTankaGraphQL()
                // simple factory function for setting up the schema
                .ConfigureSchema(() => new ValueTask<ISchema>(schema));

            /* Then */
            var provider = Services.BuildServiceProvider();
            var options = provider.GetService<IOptions<ServerOptions>>().Value;
            var actual = await options.GetSchema(null);
            Assert.Same(schema, actual);
        }

Overloads are provided for providing a function with dependencies resolved from services.


        [Fact]
        public async Task Configure_Schema_with_dependency()
        {
            /* Given */
            var schema = Substitute.For<ISchema>();

            /* When */
            Services.AddTankaGraphQL()
                // factory function with one dependency resolved from service provider
                .ConfigureSchema<IMemoryCache>(async cache =>
                    await cache.GetOrCreateAsync("schema", entry => Task.FromResult(schema)));

            /* Then */
            var provider = Services.BuildServiceProvider();
            var options = provider.GetService<IOptions<ServerOptions>>().Value;
            var actual = await options.GetSchema(null);
            Assert.Same(schema, actual);
        }

Configure rules

Configure validation rules for execution. Note that by default all rules specified in the specification are included.

Add MaxCost validation rule


        [Fact]
        public void Configure_Rules()
        {
            /* Given */
            var schema = Substitute.For<ISchema>();
            var maxCost = CostAnalyzer.MaxCost(100);

            /* When */
            Services.AddTankaGraphQL()
                .ConfigureSchema(() => new ValueTask<ISchema>(schema))
                // rules factory function with the default rules as the parameter
                .ConfigureRules(rules => rules.Concat(new []
                {
                    // append max query cost validation rule
                    maxCost
                }).ToArray());

            /* Then */
            var provider = Services.BuildServiceProvider();
            var options = provider.GetService<IOptions<ServerOptions>>().Value;
            var actual = options.ValidationRules;
            Assert.Contains(actual, rule => rule == maxCost);
        }

Remove all rules


        [Fact]
        public void Configure_Rules_remove_all()
        {
            /* Given */
            var schema = Substitute.For<ISchema>();

            /* When */
            Services.AddTankaGraphQL()
                .ConfigureSchema(() => new ValueTask<ISchema>(schema))
                // rules factory function with the default rules as the parameter
                .ConfigureRules(rules => new CombineRule[0]);

            /* Then */
            var provider = Services.BuildServiceProvider();
            var options = provider.GetService<IOptions<ServerOptions>>().Value;
            var actual = options.ValidationRules;
            Assert.Empty(actual);
        }

With up to three dependencies resolved from service provider



        [Fact]
        public void Configure_Rules_with_dependency()
        {
            /* Given */
            var schema = Substitute.For<ISchema>();

            /* When */
            Services.AddTankaGraphQL()
                .ConfigureSchema(() => new ValueTask<ISchema>(schema))
                // rules factory function with default rules and dependency resolved from service provider
                .ConfigureRules<ILogger<ServerBuilderUsageFacts>>((rules, logger) => new CombineRule[0]);

            /* Then */
            var provider = Services.BuildServiceProvider();
            var options = provider.GetService<IOptions<ServerOptions>>().Value;
            var actual = options.ValidationRules;
            Assert.Empty(actual);
        }

Add extensions

Add Apollo tracing extension


        [Fact]
        public void Add_Extension()
        {
            /* When */
            Services.AddTankaGraphQL()
                .ConfigureSchema(() => default)
                // add trace execution extension
                .AddExtension<TraceExtension>();

            /* Then */
            var provider = Services.BuildServiceProvider();
            var executorExtensions = provider.GetService<IEnumerable<IExecutorExtension>>();
            Assert.Contains(executorExtensions, extension => extension is TraceExtension);
        }