public async Task Can_delete_resource()
        {
            // Arrange
            PostOffice existingOffice = _fakers.PostOffice.Generate();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.PostOffice.Add(existingOffice);
                await dbContext.SaveChangesAsync();
            });

            string route = "/postOffices/" + existingOffice.StringId;

            // Act
            (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecuteDeleteAsync <string>(route);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.NoContent);

            responseDocument.Should().BeEmpty();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                PostOffice officeInDatabase = await dbContext.PostOffice.FirstWithIdOrDefaultAsync(existingOffice.Id);

                officeInDatabase.Should().BeNull();
            });
        }
        public async Task Can_add_to_ToMany_relationship()
        {
            // Arrange
            PostOffice existingOffice = _fakers.PostOffice.Generate();

            existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1);

            GiftCertificate existingCertificate = _fakers.GiftCertificate.Generate();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.AddRange(existingOffice, existingCertificate);
                await dbContext.SaveChangesAsync();
            });

            var requestBody = new
            {
                data = new[]
                {
                    new
                    {
                        type = "giftCertificates",
                        id   = existingCertificate.StringId
                    }
                }
            };

            string route = $"/postOffices/{existingOffice.StringId}/relationships/giftCertificates";

            // Act
            (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePostAsync <string>(route, requestBody);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.NoContent);

            responseDocument.Should().BeEmpty();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                PostOffice officeInDatabase = await dbContext.PostOffice.Include(postOffice => postOffice.GiftCertificates).FirstWithIdAsync(existingOffice.Id);

                officeInDatabase.GiftCertificates.Should().HaveCount(2);
            });
        }
        public async Task Can_update_resource_with_ToMany_relationship()
        {
            // Arrange
            var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService <ISystemClock>();

            clock.UtcNow = 19.March(1998).At(6, 34);

            PostOffice existingOffice = _fakers.PostOffice.Generate();

            existingOffice.GiftCertificates = _fakers.GiftCertificate.Generate(1);

            string newAddress = _fakers.PostOffice.Generate().Address;

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.PostOffice.Add(existingOffice);
                await dbContext.SaveChangesAsync();
            });

            var requestBody = new
            {
                data = new
                {
                    type       = "postOffices",
                    id         = existingOffice.StringId,
                    attributes = new
                    {
                        address = newAddress
                    },
                    relationships = new
                    {
                        giftCertificates = new
                        {
                            data = new[]
                            {
                                new
                                {
                                    type = "giftCertificates",
                                    id   = existingOffice.GiftCertificates[0].StringId
                                }
                            }
                        }
                    }
                }
            };

            string route = "/postOffices/" + existingOffice.StringId;

            // Act
            (HttpResponseMessage httpResponse, string responseDocument) = await _testContext.ExecutePatchAsync <string>(route, requestBody);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.NoContent);

            responseDocument.Should().BeEmpty();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                PostOffice officeInDatabase = await dbContext.PostOffice.Include(postOffice => postOffice.GiftCertificates).FirstWithIdAsync(existingOffice.Id);

                officeInDatabase.Address.Should().Be(newAddress);

                officeInDatabase.GiftCertificates.Should().HaveCount(1);
                officeInDatabase.GiftCertificates[0].Id.Should().Be(existingOffice.GiftCertificates[0].Id);
            });
        }
        public async Task Can_create_resource_with_ToOne_relationship_and_include()
        {
            // Arrange
            var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService <ISystemClock>();

            clock.UtcNow = 19.March(1998).At(6, 34);

            PostOffice existingOffice = _fakers.PostOffice.Generate();

            var newIssueDate = 18.March(1997).ToDateTimeOffset();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.PostOffice.Add(existingOffice);
                await dbContext.SaveChangesAsync();
            });

            var requestBody = new
            {
                data = new
                {
                    type       = "giftCertificates",
                    attributes = new
                    {
                        issueDate = newIssueDate
                    },
                    relationships = new
                    {
                        issuer = new
                        {
                            data = new
                            {
                                type = "postOffices",
                                id   = existingOffice.StringId
                            }
                        }
                    }
                }
            };

            const string route = "/giftCertificates?include=issuer";

            // Act
            (HttpResponseMessage httpResponse, Document responseDocument) = await _testContext.ExecutePostAsync <Document>(route, requestBody);

            // Assert
            httpResponse.Should().HaveStatusCode(HttpStatusCode.Created);

            responseDocument.SingleData.Should().NotBeNull();
            responseDocument.SingleData.Attributes["issueDate"].Should().BeCloseTo(newIssueDate);
            responseDocument.SingleData.Attributes["hasExpired"].Should().Be(true);
            responseDocument.SingleData.Relationships["issuer"].SingleData.Id.Should().Be(existingOffice.StringId);

            responseDocument.Included.Should().HaveCount(1);
            responseDocument.Included[0].Id.Should().Be(existingOffice.StringId);
            responseDocument.Included[0].Attributes["address"].Should().Be(existingOffice.Address);
            responseDocument.Included[0].Attributes["isOpen"].Should().Be(false);

            int newCertificateId = int.Parse(responseDocument.SingleData.Id);

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                GiftCertificate certificateInDatabase = await dbContext.GiftCertificates
                                                        .Include(certificate => certificate.Issuer).FirstWithIdAsync(newCertificateId);

                certificateInDatabase.IssueDate.Should().Be(newIssueDate);

                certificateInDatabase.Issuer.Should().NotBeNull();
                certificateInDatabase.Issuer.Id.Should().Be(existingOffice.Id);
            });
        }