public async Task Can_get_resource_by_ID()
        {
            // Arrange
            var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService <ISystemClock>();

            clock.UtcNow = 27.January(2021);

            GiftCertificate certificate = _fakers.GiftCertificate.Generate();

            certificate.IssueDate = 28.January(2020);

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.GiftCertificates.Add(certificate);
                await dbContext.SaveChangesAsync();
            });

            string route = "/giftCertificates/" + certificate.StringId;

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

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

            responseDocument.SingleData.Should().NotBeNull();
            responseDocument.SingleData.Id.Should().Be(certificate.StringId);
            responseDocument.SingleData.Attributes["issueDate"].Should().BeCloseTo(certificate.IssueDate);
            responseDocument.SingleData.Attributes["hasExpired"].Should().Be(false);
        }
        public async Task Can_get_secondary_resource_with_fieldset()
        {
            // Arrange
            var clock = (FrozenSystemClock)_testContext.Factory.Services.GetRequiredService <ISystemClock>();

            clock.UtcNow = 27.January(2021).At(13, 53);

            GiftCertificate certificate = _fakers.GiftCertificate.Generate();

            certificate.Issuer = _fakers.PostOffice.Generate();

            await _testContext.RunOnDatabaseAsync(async dbContext =>
            {
                dbContext.GiftCertificates.Add(certificate);
                await dbContext.SaveChangesAsync();
            });

            string route = $"/giftCertificates/{certificate.StringId}/issuer?fields[postOffices]=id,isOpen";

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

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

            responseDocument.SingleData.Should().NotBeNull();
            responseDocument.SingleData.Id.Should().Be(certificate.Issuer.StringId);
            responseDocument.SingleData.Attributes.Should().HaveCount(1);
            responseDocument.SingleData.Attributes["isOpen"].Should().Be(true);
        }
        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_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);
            });
        }