public async Task Can_Paginate_TodoItems()
        {
            // Arrange
            const int expectedEntitiesPerPage = 2;
            var       person   = new Person();
            var       todoItem = _todoItemFaker.Generate();

            todoItem.Owner = person;
            _context.TodoItems.Add(todoItem);
            _context.SaveChanges();

            var httpMethod = new HttpMethod("GET");
            var route      = $"/api/v1/todo-items?page[size]={expectedEntitiesPerPage}";

            var description = new RequestProperties("Paginate TodoItems", new Dictionary <string, string> {
                { "?page[size]=", "Number of entities per page" }
            });

            // Act
            var response = await _fixture.MakeRequest <TodoItem>(description, httpMethod, route);

            var body = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(body, _jsonApiContext);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.NotEmpty(deserializedBody);
            Assert.True(deserializedBody.Count <= expectedEntitiesPerPage);
        }
        public async Task Can_Filter_TodoItems()
        {
            // Arrange
            var person   = new Person();
            var todoItem = _todoItemFaker.Generate();

            todoItem.Ordinal = 999999;
            todoItem.Owner   = person;
            _context.TodoItems.Add(todoItem);
            _context.SaveChanges();

            var httpMethod = new HttpMethod("GET");
            var route      = $"/api/v1/todo-items?filter[ordinal]={todoItem.Ordinal}";

            var description = new RequestProperties("Filter TodoItems By Attribute", new Dictionary <string, string> {
                { "?filter[...]=", "Filter on attribute" }
            });

            // Act
            var response = await _fixture.MakeRequest <TodoItem>(description, httpMethod, route);

            var body = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(body, _jsonApiContext);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.NotEmpty(deserializedBody);

            foreach (var todoItemResult in deserializedBody)
            {
                Assert.Equal(todoItem.Ordinal, todoItemResult.Ordinal);
            }
        }
        public async Task Can_Filter_TodoItems_Using_Like_Operator()
        {
            // Arrange
            var todoItem = _todoItemFaker.Generate();

            todoItem.Ordinal = 999999;
            _context.TodoItems.Add(todoItem);
            _context.SaveChanges();
            var substring = todoItem.Description.Substring(1, todoItem.Description.Length - 2);

            var httpMethod = new HttpMethod("GET");
            var route      = $"/api/v1/todo-items?filter[description]=like:{substring}";

            var description = new RequestProperties("Filter TodoItems Where Attribute Like", new Dictionary <string, string> {
                { "?filter[...]=", "Filter on attribute" }
            });

            // Act
            var response = await _fixture.MakeRequest <TodoItem>(description, httpMethod, route);

            var body = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(body, _jsonApiContext);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.NotEmpty(deserializedBody);

            foreach (var todoItemResult in deserializedBody)
            {
                Assert.Contains(substring, todoItem.Description);
            }
        }
        public async Task Request_ForEmptyCollection_Returns_EmptyDataCollection()
        {
            // arrange
            var context = _fixture.GetService <AppDbContext>();

            context.TodoItems.RemoveRange(context.TodoItems);
            await context.SaveChangesAsync();

            var builder = new WebHostBuilder()
                          .UseStartup <Startup>();
            var httpMethod   = new HttpMethod("GET");
            var route        = "/api/v1/todo-items";
            var server       = new TestServer(builder);
            var client       = server.CreateClient();
            var request      = new HttpRequestMessage(httpMethod, route);
            var expectedBody = JsonConvert.SerializeObject(new {
                data = new List <object>()
            });

            // act
            var response = await client.SendAsync(request);

            var body = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(body, _jsonApiContext);

            // assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal("application/vnd.api+json", response.Content.Headers.ContentType.ToString());
            Assert.Empty(deserializedBody);
            Assert.Equal(expectedBody, body);

            context.Dispose();
        }
        public async Task Total_Record_Count_Included()
        {
            // arrange
            var builder = new WebHostBuilder()
                          .UseStartup <AuthorizedStartup>();
            var server         = new TestServer(builder);
            var client         = server.CreateClient();
            var context        = (AppDbContext)server.Host.Services.GetService(typeof(AppDbContext));
            var jsonApiContext = (IJsonApiContext)server.Host.Services.GetService(typeof(IJsonApiContext));

            var person = new Person();

            context.People.Add(person);
            var ownedTodoItem   = new TodoItem();
            var unOwnedTodoItem = new TodoItem();

            ownedTodoItem.Owner = person;
            context.TodoItems.Add(ownedTodoItem);
            context.TodoItems.Add(unOwnedTodoItem);
            context.SaveChanges();

            var authService = (IAuthorizationService)server.Host.Services.GetService(typeof(IAuthorizationService));

            authService.CurrentUserId = person.Id;

            var httpMethod = new HttpMethod("GET");
            var route      = $"/api/v1/todo-items?include=owner";

            var request = new HttpRequestMessage(httpMethod, route);

            // act
            var response = await client.SendAsync(request);

            var responseBody = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(responseBody, jsonApiContext);

            // assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            foreach (var item in deserializedBody)
            {
                Assert.Equal(person.Id, item.OwnerId);
            }
        }
        public async Task Can_Sort_TodoItems_By_Ordinal_Descending()
        {
            // Arrange
            _context.TodoItems.RemoveRange(_context.TodoItems);

            const int numberOfItems = 5;
            var       person        = new Person();

            for (var i = 1; i < numberOfItems; i++)
            {
                var todoItem = _todoItemFaker.Generate();
                todoItem.Ordinal = i;
                todoItem.Owner   = person;
                _context.TodoItems.Add(todoItem);
            }
            _context.SaveChanges();

            var httpMethod = new HttpMethod("GET");
            var route      = $"/api/v1/todo-items?sort=-ordinal";

            var description = new RequestProperties("Sort TodoItems Descending", new Dictionary <string, string> {
                { "?sort=-attr", "Sort on attribute" }
            });

            // Act
            var response = await _fixture.MakeRequest <TodoItem>(description, httpMethod, route);

            var body = await response.Content.ReadAsStringAsync();

            var deserializedBody = JsonApiDeSerializer.DeserializeList <TodoItem>(body, _jsonApiContext);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.NotEmpty(deserializedBody);

            long priorOrdinal = numberOfItems + 1;

            foreach (var todoItemResult in deserializedBody)
            {
                Assert.True(todoItemResult.Ordinal < priorOrdinal);
                priorOrdinal = todoItemResult.Ordinal;
            }
        }