public async Task IngestsAdvisoryWithoutVulnerability(bool withdrawn)
            {
                // Arrange
                var advisory = new SecurityAdvisory
                {
                    DatabaseId  = 1,
                    GhsaId      = "ghsa",
                    Severity    = "MODERATE",
                    WithdrawnAt = withdrawn ? new DateTimeOffset() : (DateTimeOffset?)null
                };

                PackageVulnerabilityServiceMock
                .Setup(x => x.UpdateVulnerabilityAsync(It.IsAny <PackageVulnerability>(), withdrawn))
                .Callback <PackageVulnerability, bool>((vulnerability, wasWithdrawn) =>
                {
                    Assert.Equal(advisory.DatabaseId, vulnerability.GitHubDatabaseKey);
                    Assert.Equal(PackageVulnerabilitySeverity.Moderate, vulnerability.Severity);
                    Assert.Equal(advisory.GetPermalink(), vulnerability.AdvisoryUrl);
                })
                .Returns(Task.CompletedTask)
                .Verifiable();

                // Act
                await Ingestor.IngestAsync(new[] { advisory });

                // Assert
                PackageVulnerabilityServiceMock.Verify();
            }
        private Tuple <PackageVulnerability, bool> FromAdvisory(SecurityAdvisory advisory)
        {
            var vulnerability = new PackageVulnerability
            {
                GitHubDatabaseKey = advisory.DatabaseId,
                Severity          = (PackageVulnerabilitySeverity)Enum.Parse(typeof(PackageVulnerabilitySeverity), advisory.Severity, ignoreCase: true),
                AdvisoryUrl       = advisory.GetPermalink()
            };

            foreach (var securityVulnerability in advisory.Vulnerabilities?.Edges?.Select(e => e.Node) ?? Enumerable.Empty <SecurityVulnerability>())
            {
                var packageVulnerability = FromVulnerability(vulnerability, securityVulnerability);
                vulnerability.AffectedRanges.Add(packageVulnerability);
            }

            return(Tuple.Create(vulnerability, advisory.WithdrawnAt != null));
        }
            public async Task IngestsAdvisory(bool withdrawn, bool vulnerabilityHasFirstPatchedVersion)
            {
                // Arrange
                var securityVulnerability = new SecurityVulnerability
                {
                    Package = new SecurityVulnerabilityPackage {
                        Name = "crested.gecko"
                    },
                    VulnerableVersionRange = "homeOnTheRange",
                    FirstPatchedVersion    = vulnerabilityHasFirstPatchedVersion
                        ? new SecurityVulnerabilityPackageVersion {
                        Identifier = "1.2.3"
                    } : null
                };

                var advisory = new SecurityAdvisory
                {
                    DatabaseId      = 1,
                    GhsaId          = "ghsa",
                    Severity        = "CRITICAL",
                    WithdrawnAt     = withdrawn ? new DateTimeOffset() : (DateTimeOffset?)null,
                    Vulnerabilities = new ConnectionResponseData <SecurityVulnerability>
                    {
                        Edges = new[]
                        {
                            new Edge <SecurityVulnerability>
                            {
                                Node = securityVulnerability
                            }
                        }
                    }
                };

                securityVulnerability.Advisory = advisory;

                var versionRange = VersionRange.Parse("[1.0.0, 1.0.0]");

                GitHubVersionRangeParserMock
                .Setup(x => x.ToNuGetVersionRange(securityVulnerability.VulnerableVersionRange))
                .Returns(versionRange);

                PackageVulnerabilityServiceMock
                .Setup(x => x.UpdateVulnerabilityAsync(It.IsAny <PackageVulnerability>(), withdrawn))
                .Callback <PackageVulnerability, bool>((vulnerability, wasWithdrawn) =>
                {
                    Assert.Equal(advisory.DatabaseId, vulnerability.GitHubDatabaseKey);
                    Assert.Equal(PackageVulnerabilitySeverity.Critical, vulnerability.Severity);
                    Assert.Equal(advisory.GetPermalink(), vulnerability.AdvisoryUrl);

                    var range = vulnerability.AffectedRanges.Single();
                    Assert.Equal(securityVulnerability.Package.Name, range.PackageId);
                    Assert.Equal(versionRange.ToNormalizedString(), range.PackageVersionRange);
                    Assert.Equal(securityVulnerability.FirstPatchedVersion?.Identifier, range.FirstPatchedPackageVersion);
                })
                .Returns(Task.CompletedTask)
                .Verifiable();

                // Act
                await Ingestor.IngestAsync(new[] { advisory });

                // Assert
                PackageVulnerabilityServiceMock.Verify();
            }