public async Task LimitsPageSizeIsNotSet()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();

                // maximum page size is not set and client page size is 1 and it works
                var result = await client.GetFullJsonResponseAsync("api/companies/?page[size]=1");

                var resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(1, resultCount);

                // maximum page size is not set and client page size is 1000 and it works and returns 100 records
                result = await client.GetFullJsonResponseAsync("api/companies/?page[size]=1000");

                resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(100, resultCount);

                // client page size isn't specified and it works and returns 12 records
                // as default paging for this endpoint is 12
                result = await client.GetFullJsonResponseAsync("api/companies/");

                resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(12, resultCount);
            }
        }
Example #2
0
        public async Task PagedResultOnePageResult(string baseUrl, int firstPageNumber)
        {
            int itemsCount = 10;

            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                // endpoint will return just 10 items that should be less than the whole page
                List <string> endpoints = new List <string>()
                {
                    baseUrl,
                    // lets ask for different page to be sure that it still will have correct first and last
                    $"{baseUrl}?page[number]=1",
                    // then ask for custom pageSize
                    $"{baseUrl}?page[number]=1&page[size]=15",
                    // then for custom pageSize but without pageNumber
                    $"{baseUrl}?page[size]=15"
                };

                foreach (var endpoint in endpoints)
                {
                    var result = await client.GetFullJsonResponseAsync($"{baseUrl}");

                    var resultCount = ((JArray)result.Content["data"])?.Count;
                    var last        = result.Content["links"]["last"].Value <string>();
                    var first       = result.Content["links"]["first"].Value <string>();
                    Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                    Assert.Equal(itemsCount, resultCount);
                    Assert.EndsWith($"{baseUrl}?page[number]={firstPageNumber}", first);
                    Assert.EndsWith($"{baseUrl}?page[number]={firstPageNumber}", last);
                    Assert.Null(result.Content["links"]["next"]);
                }
            }
        }
        public async Task LimitsPageSize1()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();

                // maximum page size equal to client page size and it works
                var result = await client.GetFullJsonResponseAsync("api/companies/querypagesizelimit1/?page[size]=1");

                var resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(1, resultCount);

                // maximum page size is lower than client page size and it fails
                result = await client.GetFullJsonResponseAsync("api/companies/querypagesizelimit1/?page[size]=10");

                resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode);
                Assert.Null(resultCount);

                // client page size isn't specified and it works and returns one record
                result = await client.GetFullJsonResponseAsync("api/companies/querypagesizelimit1/");

                resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(1, resultCount);
            }
        }
Example #4
0
        public async Task RequiresApiResourceProviderInstance()
        {
            var config = new JsonApiConfiguration()
            {
                ApiResourceProviderFactory = new NullApiResourceProviderFactory()
            };

            using (var server = new NewSetupJsonApiServer(config))
            {
                var client = server.GetClient();
                // id 1 is mapped to circle object
                var result = await client.GetJsonResponseAsync("api/shape/1");

                _output.WriteLine(result.ToString());

                var errors = result["errors"];
                Assert.Equal(1, errors.Count());

                var error = errors[0];

                Assert.Equal("https://github.com/joukevandermaas/saule/wiki",
                             error["links"]["about"].Value <string>());

                Assert.Equal("Saule.JsonApiException",
                             error["code"].Value <string>());

                Assert.Equal("Saule.JsonApiException: ApiResourceProviderFactory returned null but it should always return an instance of IApiResourceProvider.",
                             error["detail"].Value <string>());
            }
        }
        public async Task BuilderAndConverterConstructor()
        {
            var config = new JsonApiConfiguration
            {
                UrlPathBuilder = new CanonicalUrlPathBuilder(),
                JsonConverters = { new StringEnumConverter() }
            };

            using (var server = new NewSetupJsonApiServer(config))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/companies/456/");

                _output.WriteLine(result.ToString());

                Assert.Equal("National", result["data"]["attributes"]["location"].Value <string>());

                result = await client.GetJsonResponseAsync("api/people/");

                _output.WriteLine(result.ToString());

                var relatedUrl = result["data"][0]["relationships"]["job"]["links"]["related"]
                                 .Value <string>();
                Assert.Equal("http://localhost/corporations/456/", relatedUrl);
            }
        }
        public async Task PassesThrough400Errors()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client   = server.GetClient();
                var response = await client.GetAsync("does/not/exist");

                Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
            }
        }
        public async Task WorksForNoContent()
        {
            using (var server = new NewSetupJsonApiServer())
            {
                var client = server.GetClient();
                var result = await client.DeleteAsync("/api/companies/123");

                Assert.Equal(HttpStatusCode.NoContent, result.StatusCode);
            }
        }
        public async Task JsonApiAttributeRespondsWithJsonApi()
        {
            using (var server = new NewSetupJsonApiServer())
            {
                var client = server.GetClient(addDefaultHeaders: false);

                var result = await client.GetJsonResponseAsync("api/people/123/usingJsonApiAttributeFilter");

                Assert.NotEmpty(result["data"]["attributes"].Children());
            }
        }
        public async Task AppliesPaginationPageSizeFromAttribute()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/companies/");

                _output.WriteLine(result.ToString());

                Assert.Equal(12, (result["data"] as JArray)?.Count);
            }
        }
        public async Task AppliesPaginationPageSizeFromClient()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/companies/querypagesizelimit50/?page[size]=5");

                _output.WriteLine(result.ToString());

                var resultCount = ((JArray)result["data"])?.Count;
                Assert.Equal(5, resultCount);
            }
        }
        public async Task PassesThroughOneHttpException()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client   = server.GetClient();
                var response = await client.GetFullJsonResponseAsync("api/broken/exception");

                var errors = response.Content["errors"];

                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
                Assert.Equal(1, errors.Count());
                Assert.Equal("An error has occurred.", errors[0]["title"]);
            }
        }
Example #12
0
        public async Task CamelCaseConstructor()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration
            {
                PropertyNameConverter = new CamelCasePropertyNameConverter()
            }))
            {
                var client = server.GetClient();

                var result = await client.GetJsonResponseAsync("api/people/123");

                Assert.Null(result["data"]["attributes"]["FirstName"]);
                Assert.NotNull(result["data"]["attributes"]["firstName"]);
            }
        }
        public async Task PassesThroughHttpErrors()
        {
            using (var server = new NewSetupJsonApiServer())
            {
                var client   = server.GetClient();
                var response = await client.GetFullJsonResponseAsync("api/broken");

                _output.WriteLine(response.Content.ToString());

                var errorText = response.Content["errors"][0]["title"].Value <string>();

                Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
                Assert.Equal("Authorization has been denied for this request.", errorText);
            }
        }
        public async Task PassesThroughHttpError()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client   = server.GetClient();
                var response = await client.GetFullJsonResponseAsync("api/broken/error");

                var errors = response.Content["errors"];

                Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
                Assert.Equal(1, errors.Count());
                Assert.Equal("Error 1.", errors[0]["title"]);
                Assert.Equal("Type 1", errors[0]["code"]);
            }
        }
        public async Task DenyOtherAttributesForHandlesQuery(string query, string expectedTitle)
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();

                var response = await client.GetFullJsonResponseAsync(query);

                var error = response.Content["errors"][0];

                Assert.Equal("Saule.JsonApiException", error["code"].Value <string>());

                Assert.Equal(expectedTitle, error["title"].Value <string>());

                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
            }
        }
Example #16
0
        public async Task CamelCaseMeta()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration
            {
                PropertyNameConverter = new CamelCasePropertyNameConverter()
            }))
            {
                var client = server.GetClient();

                var result = await client.GetJsonResponseAsync("api/people/123");

                var meta = result["meta"];

                Assert.NotNull(meta["numberOfFriends"]);
                Assert.NotNull(meta["numberOfFamilyMembers"]);
            }
        }
        public async Task ConverterConstructor()
        {
            var config = new JsonApiConfiguration
            {
                JsonConverters = { new StringEnumConverter() }
            };

            using (var server = new NewSetupJsonApiServer(config))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/companies/456/");

                _output.WriteLine(result.ToString());

                Assert.Equal("National", result["data"]["attributes"]["location"].Value <string>());
            }
        }
        public async Task AppliesSortingConditionally()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/people?sort=age");

                _output.WriteLine(result.ToString());

                var ages = ((JArray)result["data"])
                           .Select(p => p["attributes"]["age"].Value <int>())
                           .ToList();
                var sorted = ages.OrderBy(a => a).ToList();

                Assert.NotEqual(sorted, ages);
            }
        }
Example #19
0
        public async Task CamelCaseNestedAttrs()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration
            {
                PropertyNameConverter = new CamelCasePropertyNameConverter()
            }))
            {
                var client = server.GetClient();

                var result = await client.GetJsonResponseAsync("api/people/123");

                var address = result["data"]["attributes"]["address"];

                Assert.NotNull(address["streetName"]);
                Assert.NotNull(address["zipCode"]);
            }
        }
        public async Task AppliesFiltering()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/query/people?filter[last-name]=Russel");

                _output.WriteLine(result.ToString());

                var names = ((JArray)result["data"])
                            .Select(p => p["attributes"]["last-name"].Value <string>())
                            .ToList();

                var filtered = names.Where(a => a == "Russel").ToList();

                Assert.Equal(filtered.Count, names.Count);
            }
        }
        public async Task LimitsPageSize()
        {
            var apiConfig = new JsonApiConfiguration
            {
                PaginationConfig = new PaginationConfig {
                    DefaultPageSize = 2, DefaultPageSizeLimit = 4
                }
            };

            using (var server = new NewSetupJsonApiServer(apiConfig))
            {
                var client = server.GetClient();
                var result = await client.GetFullJsonResponseAsync("api/companies/querypagesize/?page[size]=5");

                Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode);

                var resultCount = ((JArray)result.Content["data"])?.Count;
                Assert.Equal(null, resultCount);
            }
        }
        public async Task DefaultConstructor()
        {
            using (var server = new NewSetupJsonApiServer())
            {
                var client = server.GetClient();
                var result = await client.GetJsonResponseAsync("api/companies/456/");

                _output.WriteLine(result.ToString());

                Assert.Equal(1, result["data"]["attributes"]["location"].Value <int>());

                result = await client.GetJsonResponseAsync("api/people/");

                _output.WriteLine(result.ToString());

                var relatedUrl = result["data"][0]["relationships"]["job"]["links"]["related"]
                                 .Value <string>();
                Assert.Equal("http://localhost/api/people/0/employer/", relatedUrl);
            }
        }
        public async Task CamelCaseRelationships()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration
            {
                PropertyNameConverter = new CamelCasePropertyNameConverter()
            }))
            {
                var client = server.GetClient();

                var result = await client.GetJsonResponseAsync("api/people/123");

                var relationships = result["data"]["relationships"];

                Assert.NotNull(relationships["secretFriends"]);
                Assert.NotNull(relationships["familyMembers"]);

                Assert.Null(relationships["secret-friends"]);
                Assert.Null(relationships["family-members"]);
            }
        }
        public async Task AppliesManualIncluding(string query, string[] expectedIncludes)
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();

                var result = await client.GetJsonResponseAsync(query);

                // get all types that were included
                var includedTypes = ((JArray)result["included"])
                                    ?.Select(p => p["type"].Value <string>())
                                    .Distinct()
                                    .ToList() ?? new List <string>();

                Assert.Equal(includedTypes.Count, expectedIncludes.Length);

                foreach (var expectedInclude in expectedIncludes)
                {
                    Assert.Contains(expectedInclude, includedTypes);
                }
            }
        }
        public async Task AppliesManualFiltering(string query, int?minAge, bool?hideLastName, int expectedSize)
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                if (minAge.HasValue)
                {
                    query += $"{(query.Contains("?") ? "&" : "?")}filter[min-age]={minAge}";
                }

                if (hideLastName.HasValue)
                {
                    query += $"{(query.Contains("?") ? "&" : "?")}filter[hide-last-name]={hideLastName.Value}";
                }

                var result = await client.GetJsonResponseAsync(query);

                var data = (JArray)result["data"];

                var allLastNamesMissing = data.All(
                    p => string.IsNullOrWhiteSpace(p["attributes"]["last-name"].Value <string>()));

                // calculate count of returned records that satisfy condition
                var validCount = data.Count(p =>
                                            !minAge.HasValue ||
                                            p["attributes"]["age"].Value <int>() >= minAge.Value);

                var totalCount = ((JArray)result["data"]).Count;

                Assert.Equal(expectedSize, validCount);
                Assert.Equal(totalCount, validCount);

                if (hideLastName.HasValue)
                {
                    Assert.Equal(hideLastName.Value, allLastNamesMissing);
                }
            }
        }
        public async Task DeserializeWorks()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration
            {
                PropertyNameConverter = new CamelCasePropertyNameConverter()
            }))
            {
                var client = server.GetClient();

                var getResult = await client.GetJsonResponseAsync("api/people/123");

                getResult.Remove("included");

                var content = new StringContent(getResult.ToString());
                content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
                var postResultMessage = await client.PostAsync("api/people/123", content);

                var postResult = JObject.Parse(await postResultMessage.Content.ReadAsStringAsync());
                postResult.Remove("included");

                Assert.True(JToken.DeepEquals(getResult, postResult));
            }
        }
        public async Task GivesUsefulError()
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client   = server.GetClient();
                var response = await client.GetFullJsonResponseAsync("api/broken/123/");

                _output.WriteLine(response.ToString());

                var result = response.Content;
                var error  = result["errors"][0];

                Assert.Equal("https://github.com/joukevandermaas/saule/wiki",
                             error["links"]["about"].Value <string>());

                Assert.Equal("Saule.JsonApiException",
                             error["code"].Value <string>());

                Assert.Equal("Saule.JsonApiException: You must add a [ReturnsResourceAttribute] to action methods.",
                             error["detail"].Value <string>());

                Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
            }
        }
        public async Task AppliesSortingBeforePagination(string path)
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client  = server.GetClient();
                var result1 = await client.GetJsonResponseAsync($"api/{path}/people?sort=age");

                var result2 = await client.GetJsonResponseAsync($"api/{path}/people?sort=age&page[number]=1");

                _output.WriteLine(result1.ToString());
                _output.WriteLine(result2.ToString());

                var ages1 = ((JArray)result1["data"])
                            .Select(p => p["attributes"]["age"].Value <int>())
                            .ToList();
                var ages2 = ((JArray)result2["data"])
                            .Select(p => p["attributes"]["age"].Value <int>())
                            .ToList();

                var sorted = ages1.Concat(ages2).OrderBy(a => a).ToList();

                Assert.Equal(sorted, ages1.Concat(ages2).ToList());
            }
        }
Example #29
0
        public async Task PagedResult(object baseUrl, int firstPageNumber)
        {
            using (var server = new NewSetupJsonApiServer(new JsonApiConfiguration()))
            {
                var client = server.GetClient();
                // endpoint will return totalCount 100 items so we can calculate page numbers based on it

                // validate 100 pages by 1 page size
                var result = await client.GetFullJsonResponseAsync($"{baseUrl}?page[size]=1");

                var resultCount = ((JArray)result.Content["data"])?.Count;
                var last        = result.Content["links"]["last"].Value <string>();
                var first       = result.Content["links"]["first"].Value <string>();
                var next        = result.Content["links"]["next"].Value <string>();
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(1, resultCount);
                Assert.EndsWith($"{baseUrl}?page[size]=1&page[number]={99 + firstPageNumber}", last);
                Assert.EndsWith($"{baseUrl}?page[size]=1&page[number]={firstPageNumber}", first);
                Assert.EndsWith($"{baseUrl}?page[size]=1&page[number]={firstPageNumber + 1}", next);

                // 12 pages by 9 page size
                result = await client.GetFullJsonResponseAsync($"{baseUrl}?page[size]=9");

                resultCount = ((JArray)result.Content["data"])?.Count;
                last        = result.Content["links"]["last"].Value <string>();
                first       = result.Content["links"]["first"].Value <string>();
                next        = result.Content["links"]["next"].Value <string>();
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(9, resultCount);
                Assert.EndsWith($"{baseUrl}?page[size]=9&page[number]={11 + firstPageNumber}", last);
                Assert.EndsWith($"{baseUrl}?page[size]=9&page[number]={firstPageNumber}", first);
                Assert.EndsWith($"{baseUrl}?page[size]=9&page[number]={firstPageNumber + 1}", next);

                // 10 pages by 10 page size
                result = await client.GetFullJsonResponseAsync($"{baseUrl}?page[size]=10");

                resultCount = ((JArray)result.Content["data"])?.Count;
                last        = result.Content["links"]["last"].Value <string>();
                first       = result.Content["links"]["first"].Value <string>();
                next        = result.Content["links"]["next"].Value <string>();
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(10, resultCount);
                Assert.EndsWith($"{baseUrl}?page[size]=10&page[number]={9 + firstPageNumber}", last);
                Assert.EndsWith($"{baseUrl}?page[size]=10&page[number]={firstPageNumber}", first);
                Assert.EndsWith($"{baseUrl}?page[size]=10&page[number]={firstPageNumber + 1}", next);

                // 5 pages by 20 default page size
                result = await client.GetFullJsonResponseAsync($"{baseUrl}");

                resultCount = ((JArray)result.Content["data"])?.Count;
                last        = result.Content["links"]["last"].Value <string>();
                first       = result.Content["links"]["first"].Value <string>();
                next        = result.Content["links"]["next"].Value <string>();
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(20, resultCount);
                Assert.EndsWith($"{baseUrl}?page[number]={4 + firstPageNumber}", last);
                Assert.EndsWith($"{baseUrl}?page[number]={firstPageNumber}", first);
                Assert.EndsWith($"{baseUrl}?page[number]={firstPageNumber + 1}", next);

                // 3rd page with 20 default page size
                result = await client.GetFullJsonResponseAsync($"{baseUrl}?page[number]=2");

                resultCount = ((JArray)result.Content["data"])?.Count;
                last        = result.Content["links"]["last"].Value <string>();
                first       = result.Content["links"]["first"].Value <string>();
                next        = result.Content["links"]["next"].Value <string>();
                Assert.Equal(HttpStatusCode.OK, result.StatusCode);
                Assert.Equal(20, resultCount);
                Assert.EndsWith($"{baseUrl}?page[number]={4 + firstPageNumber}", last);
                Assert.EndsWith($"{baseUrl}?page[number]={firstPageNumber}", first);
                Assert.EndsWith($"{baseUrl}?page[number]=3", next);
            }
        }