Template
chore: deploy initial code base
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
internal class AddressInfo
|
||||
{
|
||||
public string BaseAddress { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class AllOpportunityInfo
|
||||
{
|
||||
public Guid ConfigurationGuid { get; set; }
|
||||
public string CostDriver { get; set; }
|
||||
|
||||
public bool HasInitiative { get; set; }
|
||||
|
||||
public double IdentifiedSavings { get; set; }
|
||||
public string Initiative { get; set; }
|
||||
public Guid InitiativeGuid { get; set; }
|
||||
public bool IsHidden { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Note { get; set; }
|
||||
public Guid OpportunityGuid { get; set; }
|
||||
public long OpportunityId { get; set; }
|
||||
public string OpportunityKey { get; set; }
|
||||
public int OpportunityType { get; set; }
|
||||
public string OpportunityTypeName { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class CaseTypeFamilyInfo
|
||||
{
|
||||
public int CaseTypeFamilyId { get; set; }
|
||||
public Guid CaseTypeFamilyGuid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string CaseTypeFamilyGlobalId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class ConfigurationInfo
|
||||
{
|
||||
public Guid ConfigurationGuid { get; set; }
|
||||
public string Name { get; set; }
|
||||
public byte DisplayOrder { get; set; }
|
||||
public Guid ServiceLineDimensionGuid { get; set; }
|
||||
[JsonPropertyName("entityIdsCSV")]
|
||||
public string EntityIdsCsv { get; set; }
|
||||
public bool IsUsingIndirectCost { get; set; }
|
||||
public string DepartmentRollupGlobalId { get; set; }
|
||||
public bool IsUsingCustomEntityDimension => !string.IsNullOrEmpty(DepartmentRollupGlobalId);
|
||||
[JsonPropertyName("customEntityIdsCSV")]
|
||||
public string CustomEntityIdsCsv { get; set; }
|
||||
[JsonPropertyName("fiscalYearID")]
|
||||
public short FiscalYearId { get; set; }
|
||||
public DateTime OrgDefinedEndDate { get; set; }
|
||||
public DateTime OrgDefinedTrackingCurrentMonth { get; set; }
|
||||
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class EntityIdInfo
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int EntityId { get; set; }
|
||||
[JsonPropertyName("name")]
|
||||
public string EntityName { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class EntityInfo
|
||||
{
|
||||
public string EntityTitle { get; set; }
|
||||
public string EntityLabel { get; set; }
|
||||
public string EntityText { get; set; }
|
||||
public string DepartmentRollupGlobalId { get; set; }
|
||||
public string HierarchicalGuid { get; set; }
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public class ServiceLineInfo
|
||||
{
|
||||
public string ServiceLineGlobalId { get; set; }
|
||||
public string ServiceLineTitle { get; set; }
|
||||
public string ServiceLineName { get; set; }
|
||||
public string ServiceLineDimensionGuid { get; set; }
|
||||
public string ServiceLineHierarchicalGuid { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class CostDriver
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeDefaultColumnInfo
|
||||
{
|
||||
[JsonPropertyName("index")]
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("heading")]
|
||||
public string Heading { get; set; }
|
||||
|
||||
[JsonPropertyName("isLocked")]
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
[JsonPropertyName("isHidden")]
|
||||
public bool IsHidden { get; set; }
|
||||
|
||||
[JsonPropertyName("initiativeRollupColumnId")]
|
||||
public int? InitiativeRollupColumnId { get; set; }
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeDetailColumnInfo
|
||||
{
|
||||
[JsonPropertyName("index")]
|
||||
public int Index { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("heading")]
|
||||
public string Heading { get; set; }
|
||||
|
||||
[JsonPropertyName("isLocked")]
|
||||
public bool IsLocked { get; set; }
|
||||
|
||||
[JsonPropertyName("isHidden")]
|
||||
public bool IsHidden { get; set; }
|
||||
|
||||
[JsonPropertyName("initiativeRollupColumnId")]
|
||||
public int? InitiativeRollupColumnId { get; set; }
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeFilterOptionsInfo
|
||||
{
|
||||
[JsonPropertyName("costDrivers")]
|
||||
public List<CostDriver> CostDrivers { get; set; }
|
||||
|
||||
[JsonPropertyName("costLeaders")]
|
||||
public List<CostLeader> CostLeaders { get; set; }
|
||||
|
||||
[JsonPropertyName("owners")]
|
||||
public List<Owner> Owners { get; set; }
|
||||
|
||||
[JsonPropertyName("executiveSponsors")]
|
||||
public List<ExecutiveSponsor> ExecutiveSponsors { get; set; }
|
||||
|
||||
[JsonPropertyName("workstreams")]
|
||||
public List<Workstream> Workstreams { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn1Values")]
|
||||
public object RollupColumn1Values { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn2Values")]
|
||||
public object RollupColumn2Values { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn3Values")]
|
||||
public object RollupColumn3Values { get; set; }
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeFilterSettingsInfo
|
||||
{
|
||||
[JsonPropertyName("configurationGuid")]
|
||||
public string ConfigurationGuid { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public int Status { get; set; }
|
||||
|
||||
[JsonPropertyName("costDrivers")]
|
||||
public List<string> CostDrivers { get; set; }
|
||||
|
||||
[JsonPropertyName("costLeaders")]
|
||||
public List<string> CostLeaders { get; set; }
|
||||
|
||||
[JsonPropertyName("owners")]
|
||||
public List<string> Owners { get; set; }
|
||||
|
||||
[JsonPropertyName("executiveSponsors")]
|
||||
public List<string> ExecutiveSponsors { get; set; }
|
||||
|
||||
[JsonPropertyName("workstreams")]
|
||||
public List<string> Workstreams { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn1Values")]
|
||||
public List<string> RollupColumn1Values { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn2Values")]
|
||||
public List<string> RollupColumn2Values { get; set; }
|
||||
|
||||
[JsonPropertyName("rollupColumn3Values")]
|
||||
public List<string> RollupColumn3Values { get; set; }
|
||||
|
||||
[JsonPropertyName("groupByCategory")]
|
||||
public string GroupByCategory { get; set; }
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeRollupColumnInfo
|
||||
{
|
||||
[JsonPropertyName("initiativeRollupColumnId")]
|
||||
public int InitiativeRollupColumnId { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("initiativeRollupValues")]
|
||||
public List<InitiativeRollupValue> InitiativeRollupValues { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class InitiativeRollupValue
|
||||
{
|
||||
[JsonPropertyName("initiativeRollupValueId")]
|
||||
public int InitiativeRollupValueId { get; set; }
|
||||
|
||||
[JsonPropertyName("initiativeRollupColumnId")]
|
||||
public int InitiativeRollupColumnId { get; set; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class SecurityInfo()
|
||||
{
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class User
|
||||
{
|
||||
[JsonPropertyName("userGuid")]
|
||||
public string UserGuid { get; set; }
|
||||
|
||||
[JsonPropertyName("nameFull")]
|
||||
public string NameFull { get; set; }
|
||||
}
|
||||
|
||||
public class CostLeader : User
|
||||
{
|
||||
}
|
||||
|
||||
public class ExecutiveSponsor : User
|
||||
{
|
||||
}
|
||||
|
||||
public class Owner : User
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Info
|
||||
{
|
||||
public class Workstream
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
using Riok.Mapperly.Abstractions;
|
||||
using Strata.ContinuousImprovement.Biz.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.OrgDefined.Queries;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Mapperly
|
||||
{
|
||||
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, EnumMappingIgnoreCase = true)]
|
||||
public static partial class OpportunityMetricBaseMap
|
||||
{
|
||||
public static OpportunityMetricBase Map(this ENOpportunityDataModel dataModel)
|
||||
{
|
||||
var enOpportunityBase = JsonSerializer.Deserialize<ENOpportunityBaseFilters>(dataModel.EncounterOpportunityJSON);
|
||||
OpportunityMetricBase target = new OpportunityMetricBase();
|
||||
if (enOpportunityBase != null)
|
||||
{
|
||||
target = enOpportunityBase.Map();
|
||||
target.CaseTypeIds = enOpportunityBase
|
||||
.CaseTypes.Select(fh => int.TryParse(fh.Id, out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
switch (enOpportunityBase.EncounterOpportunityLevel)
|
||||
{
|
||||
case OpportunityLevel.Entity:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Entities.Select(fh => int.TryParse(fh.Id, out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.ServiceLine:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.ServiceLines.Select(fh => int.TryParse(fh.Id, out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.Specialty:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Specialties.Select(fh => int.TryParse(fh.Id, out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.Provider:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Providers.Select(fh => int.TryParse(fh.Id, out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public static OpportunityMetricBase Map(this ENOpportunityDto source)
|
||||
{
|
||||
var target = source.MapTo();
|
||||
var enOpportunityBase = JsonSerializer.Deserialize<ENOpportunityBaseFilters>(source.EncounterOpportunityJSON);
|
||||
var regexp = new Regex(@"[^\d]*\|([\d]+)", RegexOptions.Compiled);
|
||||
if (enOpportunityBase != null)
|
||||
{
|
||||
target = enOpportunityBase.Map();
|
||||
target.CaseTypeIds = enOpportunityBase
|
||||
.CaseTypes.Select(fh => int.TryParse(regexp.Replace(fh.Id, "$1"), out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
switch (enOpportunityBase.EncounterOpportunityLevel)
|
||||
{
|
||||
case OpportunityLevel.Entity:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Entities.Select(fh => int.TryParse(regexp.Replace(fh.Id, "$1"), out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.ServiceLine:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.ServiceLines.Select(fh => int.TryParse(regexp.Replace(fh.Id, "$1"), out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.Specialty:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Specialties.Select(fh => int.TryParse(regexp.Replace(fh.Id, "$1"), out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
case OpportunityLevel.Provider:
|
||||
target.OpportunityLevelIds = enOpportunityBase
|
||||
.Providers.Select(fh => int.TryParse(regexp.Replace(fh.Id, "$1"), out var id) ? id : -1).Where(id => id >= 0).ToList();
|
||||
break;
|
||||
}
|
||||
target.OpportunityLevelIdAsCSV = string.Join(",", target.OpportunityLevelIds);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public static partial OpportunityMetricBase Map(this ENOpportunityBaseFilters enOpportunityBase);
|
||||
|
||||
[MapperIgnoreSource(nameof(ENOpportunityDto.OpportunityLevelIds))]
|
||||
private static partial OpportunityMetricBase MapTo(this ENOpportunityDto source);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Setup;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Tests;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
[SetUpFixture]
|
||||
public class ClientIntegrationTestFixture
|
||||
{
|
||||
[OneTimeSetUp]
|
||||
public virtual async Task SetDbContextAndServices()
|
||||
{
|
||||
#if DEBUG
|
||||
//When running locally sets the profile to the CI profile so you have access to resources
|
||||
Environment.SetEnvironmentVariable("AWS_Profile", "sdt-continuous-improvement-service-role");
|
||||
#endif
|
||||
var clientService = new ApiTestBase();
|
||||
await clientService.ClientValidation();
|
||||
var services = ServiceCollectionFactory.Create();
|
||||
await services.SetupServiceProperties(clientService.StrataId);
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public async Task TearDown()
|
||||
{
|
||||
try
|
||||
{
|
||||
var centralDbContext = ServiceProperties.CentralDbContext as CentralDbContext;
|
||||
if (centralDbContext == null) { return; }
|
||||
_ = await centralDbContext.Database.EnsureDeletedAsync(CancellationToken.None);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Strata.ApiLib.Core.Cors.Extensions;
|
||||
using Strata.ApiLib.Core.StrataAuthentication.Bootstrappers;
|
||||
using Strata.Configuration.Client.DependencyInjection.ConsoleApps;
|
||||
using Strata.ContinuousImprovement.Biz.Configurations;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Setup
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class ServiceCollectionFactory
|
||||
{
|
||||
// dev master
|
||||
private static readonly Guid DatabaseGuid = new("54409f55-5ddf-4748-8222-9ccfb04fb4f5");
|
||||
private static readonly string IntegrationTesting = $"ci_api_{DateTime.Now:yyyyMMdd}_{Guid.NewGuid():N}";
|
||||
|
||||
public static IServiceCollection Create()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
try
|
||||
{
|
||||
var configuration = StrataConfigurationFactory.GetConfiguration();
|
||||
services.AddSingleton(configuration);
|
||||
services.AddStrataAuthentication(configuration);
|
||||
services.AddStrataCors(configuration);
|
||||
services.AddContinuousImprovementServices(configuration, IntegrationTesting);
|
||||
services.AddAsyncDbContextFactory<JazzDbContext>(options =>
|
||||
{
|
||||
options
|
||||
.WithConnectionString((provider, token) => provider.GetConnectionStringFromSmc(DatabaseGuid, token))
|
||||
.WithDbContextOptions((connectionString, provider, builder) =>
|
||||
builder.UseSqlServer(connectionString, options => { options.CommandTimeout(300); }));
|
||||
});
|
||||
services.AddLogging();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Strata.Analytics.Client;
|
||||
using Strata.Analytics.Models.Workbooks;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Info;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.OpportunityTypeWorkbooks;
|
||||
using Strata.ContinuousImprovement.Biz.OpportunityWorkbooks;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Setup
|
||||
{
|
||||
public static class ServiceProperties
|
||||
{
|
||||
// dev master
|
||||
internal static readonly Guid DatabaseGuid = new("54409f55-5ddf-4748-8222-9ccfb04fb4f5");
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
public static ICentralDbContext CentralDbContext { get; set; }
|
||||
public static JazzEntityFrameworkFactory JazzConnBuilderFactory { get; set; }
|
||||
public static IJazzDbContext JazzDbContext { get; set; }
|
||||
public static Biz.DbContexts.Snowflake.ISnowflakeDatabaseContext SnowflakeDatabaseContext { get; set; }
|
||||
public static IServiceCollection Services { get; set; }
|
||||
public static IServiceProvider ServiceProvider { get; set; }
|
||||
public static IAnalyticsService AnalyticsService { get; set; }
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
|
||||
public static string BaseAddress { get; set; } = string.Empty;
|
||||
|
||||
private static int WorkbookId = 9;
|
||||
|
||||
public static async Task SetupServiceProperties(this IServiceCollection services, int strataId = 0)
|
||||
{
|
||||
#if DEBUG
|
||||
Environment.SetEnvironmentVariable("AWS_Profile", "sdt-continuous-improvement-service-role");
|
||||
#endif
|
||||
services.AddOptions<AddressInfo>().BindConfiguration("address").ValidateDataAnnotations(); //bind the options for aws and validates for missing values
|
||||
|
||||
Services = services;
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
ServiceProvider = serviceProvider;
|
||||
|
||||
try
|
||||
{
|
||||
var sfConnBuilderFactory = serviceProvider.GetRequiredService<Biz.DbContexts.Snowflake.ISnowflakeDatabaseContextFactory>();
|
||||
SnowflakeDatabaseContext = sfConnBuilderFactory.Create($"{DatabaseGuid:N}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ILB
|
||||
}
|
||||
var sectionAccessor = serviceProvider.GetRequiredService<IOptions<AddressInfo>>();
|
||||
var addressInfo = sectionAccessor.Value;
|
||||
if (addressInfo != null && !string.IsNullOrEmpty(addressInfo.BaseAddress))
|
||||
{
|
||||
BaseAddress = addressInfo.BaseAddress;
|
||||
}
|
||||
try
|
||||
{
|
||||
var jazzConnBuilderFactory = serviceProvider.GetRequiredService<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
JazzDbContext = await jazzConnBuilderFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ILB
|
||||
}
|
||||
|
||||
await BuildPostgresDb(strataId);
|
||||
|
||||
BuildAnalyticsService(strataId);
|
||||
}
|
||||
|
||||
private static async Task BuildPostgresDb(int strataId)
|
||||
{
|
||||
try
|
||||
{
|
||||
CentralDbContext = ServiceProvider.GetService<CentralDbContext>() as CentralDbContext
|
||||
?? throw new NullReferenceException(nameof(CentralDbContext));
|
||||
var centralDbContext = CentralDbContext as CentralDbContext;
|
||||
if (centralDbContext == null) { throw new NullReferenceException(nameof(centralDbContext)); }
|
||||
|
||||
await centralDbContext.Database.MigrateAsync(CancellationToken.None);
|
||||
Assert.That(centralDbContext, Is.Not.Null);
|
||||
|
||||
JazzConnBuilderFactory = new JazzEntityFrameworkFactory();
|
||||
await JazzConnBuilderFactory.EnsureCreatedAsync(centralDbContext, JazzDbContext, CancellationToken.None);
|
||||
var workbook = new OpportunityWorkbook
|
||||
{
|
||||
StrataId = strataId,
|
||||
WorkbookId = WorkbookId,
|
||||
OpportunityGuid = Guid.NewGuid(),
|
||||
Name = "Test",
|
||||
};
|
||||
if (!centralDbContext.OpportunityWorkbooks.Any(ow => ow.StrataId == workbook.StrataId
|
||||
&& ow.WorkbookId == workbook.WorkbookId))
|
||||
{
|
||||
await centralDbContext.OpportunityWorkbooks.AddAsync(workbook, CancellationToken.None);
|
||||
}
|
||||
var oppTypeWorkbook = new OpportunityTypeWorkbook
|
||||
{
|
||||
StrataId = strataId,
|
||||
WorkbookId = WorkbookId,
|
||||
OpportunityType = (int)OpportunityTypes.ChargeCode,
|
||||
Name = "Test",
|
||||
};
|
||||
if (!centralDbContext.OpportunityTypeWorkbooks.Any(otw => otw.StrataId == oppTypeWorkbook.StrataId
|
||||
&& otw.WorkbookId == oppTypeWorkbook.WorkbookId))
|
||||
{
|
||||
await centralDbContext.OpportunityTypeWorkbooks.AddAsync(oppTypeWorkbook, CancellationToken.None);
|
||||
}
|
||||
|
||||
await centralDbContext.SaveChangesAsync(CancellationToken.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void BuildAnalyticsService(int strataId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var analyticsService = Mock.Of<IAnalyticsService>();
|
||||
var workbook = new Workbook
|
||||
{
|
||||
Name = "Test",
|
||||
WorkbookId = WorkbookId,
|
||||
IsHidden = false,
|
||||
StrataId = strataId,
|
||||
};
|
||||
var workbooks = new List<Workbook> { workbook };
|
||||
workbooks.AddRange(Enumerable.Range(1, 1000).Where(i => i != WorkbookId).Select(i => new Workbook
|
||||
{
|
||||
Name = $"Test {i}",
|
||||
WorkbookId = i,
|
||||
IsHidden = (i % 2 == 0),
|
||||
StrataId = (i % 3 == 0) ? 9 : strataId,
|
||||
}));
|
||||
//GetWorkbooksAsync
|
||||
Mock.Get(analyticsService)
|
||||
.Setup(s => s.GetWorkbookAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<int, CancellationToken>((id, token)
|
||||
=> Task.FromResult(id == WorkbookId ? workbook : null));
|
||||
Mock.Get(analyticsService)
|
||||
.Setup(s => s.GetWorkbooksAsync(It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<bool, CancellationToken>((isHidden, token)
|
||||
=> Task.FromResult(workbooks.Where(w => w.IsHidden == isHidden)));
|
||||
AnalyticsService = analyticsService;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Setup
|
||||
{
|
||||
public class VaultResponse
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.400.36" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.7.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
|
||||
<PackageReference Include="Strata.ApiLib.Core" Version="8.4.1" />
|
||||
<PackageReference Include="Strata.Configuration.Client" Version="9.15.1" />
|
||||
<PackageReference Include="Strata.SnowflakeLib" Version="4.3.0" />
|
||||
<PackageReference Include="Strata.SqlTools.EntityFramework" Version="6.0.3" />
|
||||
<PackageReference Include="Verify.NUnit" Version="29.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Strata.ContinuousImprovement.Api\Strata.ContinuousImprovement.Api.csproj" />
|
||||
<ProjectReference Include="..\..\src\Strata.ContinuousImprovement.Biz\Strata.ContinuousImprovement.Biz.csproj" />
|
||||
<ProjectReference Include="..\Strata.ContinuousImprovement.JazzEntityFrameworkStub\Strata.ContinuousImprovement.JazzEntityFrameworkStub.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="NUnit.Framework" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,222 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Setup;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.OpportunityTypeWorkbooks;
|
||||
using Strata.ContinuousImprovement.Biz.OpportunityWorkbooks;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.CoreLib.Claims.Extensions;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Json;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
public class ApiTestBase
|
||||
{
|
||||
protected StrataTokenInfo StrataTokenInfo { get; set; }
|
||||
protected string AccessToken { get; set; }
|
||||
protected IEnumerable<Claim> Claims { get; set; }
|
||||
protected long Expires_in { get; set; }
|
||||
protected ClaimsIdentity ClaimsIdentity { get; set; }
|
||||
protected ClaimsPrincipal ClaimsPrincipal { get; set; }
|
||||
protected Dictionary<string, ClaimsPrincipal> ClaimsPrincipals { get; set; } = new Dictionary<string, ClaimsPrincipal>();
|
||||
internal IClaimsPrincipalAccessor ClaimsPrincipalAccessor { get; set; }
|
||||
internal int StrataId { get; set; }
|
||||
internal Guid DatabaseGuid { get; set; }
|
||||
|
||||
protected readonly string BaseAddress = "https://continuousimprovement-api.dev.stratanetwork.net";
|
||||
public IConfigurationService ConfigurationService { get; set; }
|
||||
public CentralDbContext CentralDbContext { get; set; }
|
||||
public IOpportunityWorkbookService OpportunityWorkbookService { get; set; }
|
||||
#pragma warning disable NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method
|
||||
|
||||
public OpportunityWorkbook OpportunityWorkbook { get; set; }
|
||||
public OpportunityTypeWorkbook OpportunityTypeWorkbook { get; set; }
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task TestSetup()
|
||||
{
|
||||
#if DEBUG
|
||||
//When running locally sets the profile to the CI profile so you have access to resources
|
||||
Environment.SetEnvironmentVariable("AWS_Profile", "sdt-continuous-improvement-service-role");
|
||||
#endif
|
||||
var strataBearer = await StrataValidation();
|
||||
await ClientValidation();
|
||||
var services = ServiceCollectionFactory.Create();
|
||||
await services.SetupServiceProperties(StrataId);
|
||||
ServiceProvider = ServiceProperties.ServiceProvider;
|
||||
var httpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(BaseAddress)
|
||||
};
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
|
||||
CentralDbContext = (CentralDbContext)ServiceProperties.CentralDbContext;
|
||||
}
|
||||
|
||||
protected HttpClient HttpClient;
|
||||
|
||||
[SetUp]
|
||||
public void SetupHttpClient()
|
||||
{
|
||||
HttpClient = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(BaseAddress)
|
||||
};
|
||||
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDownHttpClient()
|
||||
{
|
||||
HttpClient.Dispose();
|
||||
}
|
||||
|
||||
#region Client Claims Validation
|
||||
|
||||
public async Task<string> ClientValidation()
|
||||
{
|
||||
var userInfo = new VaultUserInfo
|
||||
{
|
||||
vaultTitle = "ccicostleader", // vault ccicostleader is same as jazz ccicostleader
|
||||
vaultUserName = "ccicostleader",
|
||||
userName = "ccicostleader",
|
||||
fullName = "Administrator, CCI"
|
||||
};
|
||||
return await ClientValidation(userInfo);
|
||||
}
|
||||
|
||||
public async Task<string> StrataValidation()
|
||||
{
|
||||
var userInfo = new VaultUserInfo
|
||||
{
|
||||
vaultTitle = "IDTestUser", // vault ccicostleader is same as jazz ccicostleader
|
||||
vaultUserName = "sdt\\IDTestUser", // vault ccicostleader is same as jazz ccicostleader
|
||||
userName = "sdt\\IDTestUser",
|
||||
fullName = "Administrator, CCI"
|
||||
};
|
||||
return await ClientValidation(userInfo);
|
||||
}
|
||||
|
||||
public async Task<string> ClientValidation(VaultUserInfo userInfo)
|
||||
{
|
||||
var vaultInfo = await GetUserPassword(userInfo.vaultTitle);
|
||||
var bearerToken = await GetBearerToken(vaultInfo.Item1, vaultInfo.Item2);
|
||||
ClaimsIdentity = new ClaimsIdentity(Claims);
|
||||
ClaimsPrincipal = new ClaimsPrincipal(ClaimsIdentity);
|
||||
ClaimsPrincipals.Add(userInfo.vaultTitle, ClaimsPrincipal);
|
||||
StrataId = ClaimsPrincipal.GetStrataId();
|
||||
DatabaseGuid = ClaimsPrincipal.GetDatabaseGuid();
|
||||
BuildClaimsPrincipalAccessor();
|
||||
return bearerToken;
|
||||
}
|
||||
|
||||
internal async Task<Tuple<string, string>> GetUserPassword(string vaultTitle)
|
||||
{
|
||||
var client = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri("https://vault.sdt.local/")
|
||||
};
|
||||
client.DefaultRequestHeaders.Add("apiKey", "a69d2e478c3f5b395b687ecdf34a3239");
|
||||
client.DefaultRequestHeaders.Add("ignoreHTTPSErrors", "true");
|
||||
var vaultResponse = await client.GetAsync($"api/searchpasswords/122?title={vaultTitle}");
|
||||
vaultResponse.EnsureSuccessStatusCode();
|
||||
string responseString = await vaultResponse.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrEmpty(responseString)) { return new Tuple<string, string>(string.Empty, string.Empty); }
|
||||
var jsonResponse = JsonSerializer.Deserialize<IEnumerable<VaultResponse>>(responseString);
|
||||
if (jsonResponse == null) { return new Tuple<string, string>(string.Empty, string.Empty); }
|
||||
var vaultUserInfo = jsonResponse.First();
|
||||
client.Dispose();
|
||||
return new Tuple<string, string>(vaultUserInfo.UserName, vaultUserInfo.Password);
|
||||
}
|
||||
|
||||
internal async Task<string> GetBearerToken(string userName, string password)
|
||||
{
|
||||
var form = BuildTokenRequest(userName, password);
|
||||
var client = new HttpClient();
|
||||
var response = await client.PostAsync("https://identity.dev.stratanetwork.net/connect/token", form);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseString = await response.Content.ReadAsStringAsync();
|
||||
if (string.IsNullOrEmpty(responseString)) { return string.Empty; }
|
||||
var strataTokenInfo = JsonSerializer.Deserialize<StrataTokenInfo>(responseString);
|
||||
if (strataTokenInfo == null) { return string.Empty; }
|
||||
StrataTokenInfo = strataTokenInfo;
|
||||
AccessToken = strataTokenInfo.AccessToken;
|
||||
Expires_in = strataTokenInfo.ExpiresIn;
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jwtToken = handler.ReadJwtToken(AccessToken);
|
||||
Claims = jwtToken.Claims;
|
||||
client.Dispose();
|
||||
return AccessToken;
|
||||
}
|
||||
|
||||
internal FormUrlEncodedContent BuildTokenRequest(string userName, string password)
|
||||
{
|
||||
var form = new FormUrlEncodedContent(
|
||||
[
|
||||
new KeyValuePair<string, string>("database_guid", ServiceProperties.DatabaseGuid.ToString()),
|
||||
new KeyValuePair<string, string>("grant_type", "password"),
|
||||
new KeyValuePair<string, string>("username", userName),
|
||||
new KeyValuePair<string, string>("password", password),
|
||||
new KeyValuePair<string, string>("scope", "strata.api.external offline_access"),
|
||||
new KeyValuePair<string, string>("client_id", "IntegrationTest"),
|
||||
new KeyValuePair<string, string>("client_secret", "UhAEQsGByTCrwPdHPLmaet_DmLEfcJVbZqGBxArdeRup_TPLrYKNpUNRHejjdnhd")
|
||||
]);
|
||||
return form;
|
||||
}
|
||||
|
||||
internal void BuildClaimsPrincipalAccessor()
|
||||
{
|
||||
try
|
||||
{
|
||||
var claimsAccessor = Mock.Of<IClaimsPrincipalAccessor>();
|
||||
Mock.Get(claimsAccessor)
|
||||
.Setup(s => s.GetCurrentClaimsPrincipal())
|
||||
.Returns(ClaimsPrincipal);
|
||||
ClaimsPrincipalAccessor = claimsAccessor;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
protected async Task<IEnumerable<Info.ConfigurationInfo>> GetConfigurations()
|
||||
{
|
||||
string ConfigurationsEndpoint = "api/v1/configurations";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, ConfigurationsEndpoint);
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurations = await response.Content.ReadFromJsonAsync<IEnumerable<Info.ConfigurationInfo>>();
|
||||
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
|
||||
configurations = configurations?.OrderBy(x => x.DisplayOrder)
|
||||
?? throw new ArgumentNullException(nameof(configurations));
|
||||
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
|
||||
return configurations;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public class VaultUserInfo
|
||||
{
|
||||
public string vaultTitle { get; set; }
|
||||
public string vaultUserName { get; set; }
|
||||
public string userName { get; set; }
|
||||
public string fullName { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
public static class HttpMessageResponseExtensions
|
||||
{
|
||||
public static void AssertIsValid(this HttpResponseMessage response, bool exportable = false, string version = "1.0")
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(response.IsSuccessStatusCode, Is.True);
|
||||
var headers = response.Headers.Where(x => x.Value != null)
|
||||
.ToDictionary(k => k.Key, v => v.Value);
|
||||
Assert.That(headers, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(headers.ContainsKey("Api-Supported-Versions"), Is.True);
|
||||
var apiVersion = headers["Api-Supported-Versions"].ToList();
|
||||
Assert.That(apiVersion.Contains(version), Is.True);
|
||||
if (exportable)
|
||||
{
|
||||
var content = response.Content;
|
||||
Assert.That(content, Is.Not.Null);
|
||||
headers = response.Content.Headers.Where(x => x.Value != null)
|
||||
.ToDictionary(k => k.Key, v => v.Value);
|
||||
Assert.That(headers.ContainsKey("Content-Type"), Is.True);
|
||||
var contentType = headers["Content-Type"].ToList();
|
||||
Assert.That(contentType.Contains("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"), Is.True);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
public class StrataTokenInfo
|
||||
{
|
||||
[JsonPropertyName("access_token")]
|
||||
public required string AccessToken { get; set; }
|
||||
[JsonPropertyName("token_type")]
|
||||
public required string TokenType { get; set; }
|
||||
[JsonPropertyName("expires_in")]
|
||||
public required long ExpiresIn { get; set; }
|
||||
[JsonPropertyName("refresh_token")]
|
||||
public required string RefreshToken { get; set; }
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
using Strata.ApiCommunication.Http;
|
||||
using Strata.ApiLib.Standard.Models;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture(Category = "Integration")]
|
||||
|
||||
public class TestAllOpportunitiesController : ApiTestBase
|
||||
{
|
||||
protected const string AllOpportunitiesEndpoint = "api/v1/all-opportunities";
|
||||
|
||||
[Test]
|
||||
public async Task TestGetAllOportunitiesFromApi()
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.First();
|
||||
var loadOptions = new Controllers.AllOpportunityLoadOptions
|
||||
{
|
||||
Filters = new Biz.All.Opportunities.Filters.AllFilters
|
||||
{
|
||||
ConfigurationGuid = configuration.ConfigurationGuid,
|
||||
OpportunityTypes =
|
||||
[
|
||||
$"{(int)OpportunityTypes.Encounter}",
|
||||
$"{(int) OpportunityTypes.QualityVariation}",
|
||||
$"{(int) OpportunityTypes.Variation}",
|
||||
],
|
||||
ViewVisible = true
|
||||
},
|
||||
PagingOptions = new Biz.Pagination.PagingOptions
|
||||
{
|
||||
First = 0,
|
||||
Rows = 100,
|
||||
SortOrder = Biz.Pagination.SortOrder.Desc,
|
||||
SortField = "IdentifiedSavings"
|
||||
}
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, AllOpportunitiesEndpoint);
|
||||
|
||||
// act
|
||||
await request.SetContentAsJsonAsync(loadOptions);
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
var opportunitiesPage = new PagedApiResponse<Info.AllOpportunityInfo>();
|
||||
Assert.DoesNotThrowAsync(async () =>
|
||||
opportunitiesPage = await response.Content.ReadFromJsonAsync<PagedApiResponse<Info.AllOpportunityInfo>>());
|
||||
response.AssertIsValid();
|
||||
Assert.That(opportunitiesPage.Data, Is.Not.Empty);
|
||||
Assert.That(opportunitiesPage.Data.Count, Is.LessThanOrEqualTo(loadOptions.PagingOptions.Rows));
|
||||
Assert.That(opportunitiesPage.Data.Any(opp =>
|
||||
opp.OpportunityType == (int)OpportunityTypes.Encounter
|
||||
|| opp.OpportunityType == (int)OpportunityTypes.QualityVariation
|
||||
|| opp.OpportunityType == (int)OpportunityTypes.Variation), Is.True);
|
||||
Assert.That(opportunitiesPage.PagingInfo.ResultsPerPage, Is.LessThanOrEqualTo(loadOptions.PagingOptions.Rows));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using Strata.DecisionSupport.Models.Jazz;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture(Category = "Integration")]
|
||||
|
||||
public class TestClientOpportunityWorkbooksController : ApiTestBase
|
||||
{
|
||||
protected const string ClientOpportunityWorkbooksEndpoint = "api/v1/client-opportunity-workbooks";
|
||||
|
||||
[Test]
|
||||
public async Task TestGetAllWorkbooksFromApi()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, $"{ClientOpportunityWorkbooksEndpoint}/workbooks");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var workbooks = await response.Content.ReadFromJsonAsync<IEnumerable<WorkbookClientInfo>>(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(workbooks, Is.AssignableTo<IEnumerable<WorkbookClientInfo>>());
|
||||
Assert.That(workbooks, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Integration"), Category("API")]
|
||||
|
||||
public partial class TestConfigurationsController : ApiTestBase
|
||||
{
|
||||
protected const string ConfigurationsEndpoint = "api/v1/configurations";
|
||||
|
||||
[Test]
|
||||
public async Task TestConfigurations()
|
||||
{
|
||||
//arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, ConfigurationsEndpoint);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
response.AssertIsValid();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Test database needs to be rolled over to the new year")]
|
||||
public async Task TestDfltConfiguration()
|
||||
{
|
||||
//arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, ConfigurationsEndpoint);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurations = await response.Content.ReadFromJsonAsync<IEnumerable<Info.ConfigurationInfo>>();
|
||||
configurations = configurations?.OrderBy(x => x.DisplayOrder);
|
||||
var configuration = configurations?.FirstOrDefault();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
|
||||
Assert.That(configurations, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configuration, Is.Not.Null);
|
||||
var expectedFiscalYearId = DateTime.Now.Year;
|
||||
Assert.That(configuration.FiscalYearId, Is.InRange(expectedFiscalYearId - 1, expectedFiscalYearId), "Test database fiscal year configuration must be updated for the current year.");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestEntityConfiguration()
|
||||
{
|
||||
//arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, ConfigurationsEndpoint);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurations = await response.Content.ReadFromJsonAsync<IEnumerable<Info.ConfigurationInfo>>();
|
||||
configurations = configurations?.OrderBy(x => x.DisplayOrder);
|
||||
var configuration = configurations?.FirstOrDefault(c => c.EntityIdsCsv != "" && !c.IsUsingCustomEntityDimension);
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
|
||||
Assert.That(configurations, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configuration, Is.Not.Null);
|
||||
Assert.That(configuration.IsUsingCustomEntityDimension, Is.False);
|
||||
Assert.That(configuration.EntityIdsCsv, Is.Not.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestConfigurationEntities()
|
||||
{
|
||||
//arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configurationGuid = configurations?.FirstOrDefault(c => c.EntityIdsCsv != "" && !c.IsUsingCustomEntityDimension)?.ConfigurationGuid ?? Guid.Empty;
|
||||
var configurationsEndpoint = ConfigurationsEndpoint + $"/{configurationGuid}/configuration-entities";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, configurationsEndpoint);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurationEntities = await response.Content.ReadFromJsonAsync<IEnumerable<Info.EntityIdInfo>>();
|
||||
configurationEntities = configurationEntities?.OrderBy(x => x.EntityName);
|
||||
var configurationEntity = configurationEntities?.FirstOrDefault();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
|
||||
Assert.That(configurationEntities, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configurationEntity, Is.Not.Null);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestConfigurationServiceLineInfo()
|
||||
{
|
||||
//arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configurationGuid = configurations?.FirstOrDefault()?.ConfigurationGuid ?? Guid.Empty;
|
||||
var configurationsEndpoint = ConfigurationsEndpoint + $"/{configurationGuid}/configuration-service-line-info";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, configurationsEndpoint);
|
||||
var guidRegex = GuidRegex();
|
||||
var serviceLineRegex = new Regex("w*Service Lines?");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurationServiceLine = await response.Content.ReadFromJsonAsync<Info.ServiceLineInfo>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
|
||||
Assert.That(configurationServiceLine, Is.Not.Null);
|
||||
Assert.That(configurationServiceLine.ServiceLineGlobalId, Is.Not.Null);
|
||||
Assert.That(configurationServiceLine.ServiceLineTitle, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configurationServiceLine.ServiceLineName, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(guidRegex.IsMatch(configurationServiceLine.ServiceLineDimensionGuid), Is.True);
|
||||
Assert.That(guidRegex.IsMatch(configurationServiceLine.ServiceLineHierarchicalGuid), Is.True);
|
||||
Assert.That(serviceLineRegex.IsMatch(configurationServiceLine.ServiceLineTitle), Is.True);
|
||||
Assert.That(serviceLineRegex.IsMatch(configurationServiceLine.ServiceLineName), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestConfigurationEntityInfo()
|
||||
{
|
||||
//arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configurationGuid = configurations?.FirstOrDefault()?.ConfigurationGuid ?? Guid.Empty;
|
||||
var configurationsEndpoint = ConfigurationsEndpoint + $"/{configurationGuid}/configuration-entity-info";
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, configurationsEndpoint);
|
||||
var guidRegex = GuidRegex();
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var configurationServiceLine = await response.Content.ReadFromJsonAsync<Info.EntityInfo>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
|
||||
Assert.That(configurationServiceLine, Is.Not.Null);
|
||||
Assert.That(configurationServiceLine.DepartmentRollupGlobalId, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configurationServiceLine.EntityTitle, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configurationServiceLine.EntityLabel, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(configurationServiceLine.EntityText, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(guidRegex.IsMatch(configurationServiceLine.HierarchicalGuid), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
[GeneratedRegex("[({]?[a-fA-F0-9]{8}[\\-]?([a-fA-F0-9]{4}[\\-]?){3}[a-fA-F0-9]{12}[})]?")]
|
||||
private static partial Regex GuidRegex();
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
using Strata.ApiCommunication.Http;
|
||||
using Strata.ApiLib.Standard.Models;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Mapperly;
|
||||
using Strata.ContinuousImprovement.Biz.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.OrgDefined.Queries;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[TestFixture, Category("Integration"), Category("API")]
|
||||
|
||||
public class TestEncounterOpportunitiesController : ApiTestBase
|
||||
{
|
||||
private const string EncounterOpportunitiesEndpoint = "api/v1/encounter-opportunities";
|
||||
|
||||
[Test]
|
||||
public async Task OpportunityMetricCohortDataTest()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "api/v1/configurations");
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
var configurations = await response.Content
|
||||
.ReadFromJsonAsync<List<ConfigurationInfo>>(options, CancellationToken.None);
|
||||
var configuration = configurations.SingleOrDefault(c => c.DisplayOrder == 0);
|
||||
if (configuration == null) Assert.Inconclusive("Unable to obtain configuration");
|
||||
request = new HttpRequestMessage(HttpMethod.Post, EncounterOpportunitiesEndpoint);
|
||||
await request.SetContentAsJsonAsync(
|
||||
new
|
||||
{
|
||||
pagingOptions = new
|
||||
{
|
||||
sortField = "IdentifiedSavings",
|
||||
sortOrder = "Asc",
|
||||
first = 0,
|
||||
rows = 1
|
||||
},
|
||||
filters = new
|
||||
{
|
||||
configurationGuid = configuration.ConfigurationGuid,
|
||||
identifiedSavings = 0,
|
||||
viewVisible = true,
|
||||
excludeInitiaves = false,
|
||||
opportunitySearch = "",
|
||||
cases = 0,
|
||||
opportunityLevels = Array.Empty<string>(),
|
||||
encounterGroups = "CaseType",
|
||||
seasonality = "Without"
|
||||
}
|
||||
});
|
||||
response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var opportunityPage =
|
||||
await response.Content.ReadFromJsonAsync<PagedApiResponse<ENOpportunity>>(options, CancellationToken.None);
|
||||
var opportunity = opportunityPage?.Data.FirstOrDefault(opp => opp.OpportunityLevel == nameof(OpportunityLevel.Entity));
|
||||
if (opportunity == null) Assert.Ignore("No Encounter Opportunity found to work with");
|
||||
request = new HttpRequestMessage(HttpMethod.Get, EncounterOpportunitiesEndpoint + $"/{opportunity.OpportunityGuid}");
|
||||
response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var opportunityDto = await response.Content.ReadFromJsonAsync<ENOpportunityDto>(options, CancellationToken.None);
|
||||
if (opportunityDto == null) Assert.Ignore("Unable to retrieve opportunity data");
|
||||
var data = opportunityDto.Map();
|
||||
var caseTypeCategorySql = string.Empty;
|
||||
/*
|
||||
var CaseTypeCategories = await jazzDbContext.DimCaseTypes
|
||||
.GroupBy(ct => ct.CaseTypeCategory, (g, d) => new
|
||||
{
|
||||
CaseTypeCategory = g,
|
||||
CaseTypeIds = d.Select(x => x.CaseTypeId).ToList()
|
||||
}).ToListAsync(CancellationToken.None);
|
||||
var CaseTypeCategorySql = CaseTypeCategories
|
||||
.Select(ct => string.Format(CaseTypeFamilyIdExists.Exists[ct.CaseTypeCategory], string.Join(",", ct.CaseTypeIds)))
|
||||
.Aggregate("", (x, y) => $"{x}\r\nOR\r\n{y}");
|
||||
*/
|
||||
var requestInfo = new OpportunityMetricCohortOptions
|
||||
{
|
||||
ConfigurationGuid = configuration.ConfigurationGuid,
|
||||
Data = data,
|
||||
InnerJoin = caseTypeCategorySql
|
||||
};
|
||||
request = new HttpRequestMessage(HttpMethod.Post, $"{EncounterOpportunitiesEndpoint}/opportunity-metric-cohort-data");
|
||||
await request.SetContentAsJsonAsync(requestInfo, CancellationToken.None);
|
||||
|
||||
// Act
|
||||
response = await HttpClient.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigurationInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Guid ConfigurationGuid { get; set; }
|
||||
public int DisplayOrder { get; set; }
|
||||
public int FiscalYearId { get; set; }
|
||||
}
|
||||
|
||||
public class ENOpportunityInfo
|
||||
{
|
||||
public Guid OpportunityGuid { get; set; }
|
||||
public Guid ConfigurationGuid { get; set; }
|
||||
public string OpportunityKey { get; set; }
|
||||
public double IdentifiedSavings { get; set; }
|
||||
public Guid InitiativeGuid { get; set; }
|
||||
public bool HasInitiative => InitiativeGuid != Guid.Empty;
|
||||
public string Initiative { get; set; }
|
||||
public bool IsHidden { get; set; }
|
||||
public string Note { get; set; } = String.Empty;
|
||||
public string Name { get; set; }
|
||||
public double Cases { get; set; }
|
||||
public string EncounterGroup { get; set; }
|
||||
public string EncounterGroupValue { get; set; }
|
||||
public string OpportunityLevel { get; set; }
|
||||
public bool IsSeasonal { get; set; }
|
||||
public long OpportunityId { get; set; }
|
||||
}
|
||||
|
||||
public static class CaseTypeFamilyIdExists
|
||||
{
|
||||
public static string[] Exists => new[]
|
||||
{
|
||||
@" EXISTS(SELECT 1 FROM dss.CaseTypeFamilyMappingICD10 msdrg
|
||||
INNER JOIN dss.DimCaseType dct ON dct.CaseTypeFamilyID = msdrg.CaseTypeFamilyID AND dct.CaseTypeId in ({0}) AND dct.CaseTypeCategory = 0
|
||||
WHERE msdrg.CaseTypeFamilyID = fpes.MSDRGCaseTypeFamilyID)",
|
||||
@" EXISTS(SELECT 1 FROM dss.CaseTypeFamilyMappingAPRDRG aprdrg
|
||||
INNER JOIN dss.DimCaseType dct ON dct.CaseTypeFamilyID = aprdrg.CaseTypeFamilyID AND dct.CaseTypeId in ({0}) AND dct.CaseTypeCategory = 1
|
||||
WHERE aprdrg.CaseTypeFamilyID = fpes.APRDRGCaseTypeFamilyID)",
|
||||
@"AND EXISTS(SELECT 1 FROM dss.FactPatientEncounterClinicalIndicator ci
|
||||
WHERE ci.EncounterID = fpes.EncounterID AND ci.ClinicalIndicatorID in ({0}) and ci.IsDeleted = 0)",
|
||||
@" EXISTS(SELECT 1 FROM dss.CaseTypeFamilyMappingCPT cpt
|
||||
INNER JOIN dss.DimCaseType dct ON dct.CaseTypeFamilyID = cpt.CaseTypeFamilyID AND dct.CaseTypeId in ({0}) AND dct.CaseTypeCategory = 3
|
||||
WHERE cpt.CaseTypeFamilyID = fpes.CPTCodeCaseTypeFamilyID)"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Setup;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture(Category = "Integration")]
|
||||
public class TestFixtureSetup : ApiTestBase
|
||||
{
|
||||
[Test]
|
||||
public async Task TestBearerToken()
|
||||
{
|
||||
var bearerToken = AccessToken;
|
||||
Assert.That(bearerToken, Is.Not.Null.And.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestCentralDbContext()
|
||||
{
|
||||
var centralDbContext = ServiceProperties.CentralDbContext as CentralDbContext;
|
||||
Assert.That(centralDbContext, Is.Not.Null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
using Strata.ApiCommunication.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[TestFixture(Category = "Integration")]
|
||||
public class TestInitiativesController : ApiTestBase
|
||||
{
|
||||
protected const string InitiativesEndpoint = "api/v1/initiatives";
|
||||
protected const string InitiativesDetailColumnsEndpoint = "api/v1/initiative-detail-columns";
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiatives()
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
var data = new
|
||||
{
|
||||
configurationGuid,
|
||||
name = "",
|
||||
status = 0,
|
||||
costDrivers = Array.Empty<string>(),
|
||||
costLeaders = Array.Empty<string>(),
|
||||
owners = Array.Empty<string>(),
|
||||
executiveSponsors = Array.Empty<string>(),
|
||||
workstreams = Array.Empty<string>(),
|
||||
rollupColumn1Values = Array.Empty<string>(),
|
||||
rollupColumn2Values = Array.Empty<string>(),
|
||||
rollupColumn3Values = Array.Empty<string>(),
|
||||
groupByCategory = "CostDriver"
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, InitiativesEndpoint);
|
||||
await request.SetContentAsJsonAsync(data);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var initiatives = await response.Content.ReadFromJsonAsync<IEnumerable<dynamic>>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(initiatives, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiativesCriteria()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, InitiativesEndpoint + "/criteria");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var initiativesCriteria = await response.Content.ReadFromJsonAsync<IEnumerable<dynamic>>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(initiativesCriteria, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiativesDetailColumnList()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "api/v1/initiative-detail-columns/column-list");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var detailColumns = await response.Content.ReadFromJsonAsync<IEnumerable<dynamic>>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(detailColumns, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiativesDefaultColumnList()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "api/v1/initiative-detail-columns/default-column-list");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var detailColumns = await response.Content.ReadFromJsonAsync<IEnumerable<dynamic>>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(detailColumns, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiativesFilterOptions()
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, InitiativesEndpoint + $"/{configurationGuid}/filter-options");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var filterOptions = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(filterOptions, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
[Test]
|
||||
public async Task TestInitiativesFilterSettings()
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, InitiativesEndpoint + $"/filter-settings");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var filterSettings = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(filterSettings, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestInitiativesExport()
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
var data = new
|
||||
{
|
||||
sortOptions = new
|
||||
{
|
||||
sortField = "name",
|
||||
sortOrder = "Asc"
|
||||
},
|
||||
filters = new
|
||||
{
|
||||
configurationGuid,
|
||||
groupByCategory = "CostDriver"
|
||||
}
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, InitiativesEndpoint + "/export?exportAll=true");
|
||||
await request.SetContentAsJsonAsync(data);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// assert
|
||||
response.AssertIsValid(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
using Strata.ApiCommunication.Http;
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Info;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[TestFixture(), Category("Integration"), Category("API")]
|
||||
public class TestInitiativesController_Export : ApiTestBase
|
||||
{
|
||||
protected const string InitiativesEndpoint = "api/v1/initiatives";
|
||||
private Guid ConfigurationGuid { get; set; } = Guid.Empty;
|
||||
private string Workstream { get; set; } = string.Empty;
|
||||
private object FilterSettings { get; set; }
|
||||
|
||||
[Test, Order(1)]
|
||||
public async Task TestInitiativesExport_Step1()
|
||||
{
|
||||
// arrange
|
||||
|
||||
// act
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
ConfigurationGuid = configurationGuid;
|
||||
|
||||
// assert
|
||||
Assert.That(ConfigurationGuid, Is.Not.EqualTo(Guid.Empty));
|
||||
}
|
||||
|
||||
[Test, Order(2)]
|
||||
public async Task TestInitiativesExport_Step2()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, InitiativesEndpoint + $"/{ConfigurationGuid}/filter-options");
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var filterOptions = await response.Content.ReadFromJsonAsync<InitiativeFilterOptionsInfo>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(filterOptions, Is.Not.Null);
|
||||
Assert.That(filterOptions.Workstreams, Is.Not.Null.And.Not.Empty);
|
||||
});
|
||||
var workstream = filterOptions.Workstreams.First().Name;
|
||||
Workstream = workstream;
|
||||
}
|
||||
|
||||
[Test, Order(3)]
|
||||
public async Task TestInitiativesExport_Step3()
|
||||
{
|
||||
// arrange
|
||||
FilterSettings = new
|
||||
{
|
||||
ConfigurationGuid,
|
||||
name = "",
|
||||
status = 0,
|
||||
costDrivers = Array.Empty<string>(),
|
||||
costLeaders = Array.Empty<string>(),
|
||||
owners = Array.Empty<string>(),
|
||||
executiveSponsors = Array.Empty<string>(),
|
||||
workstreams = new string[] { Workstream },
|
||||
rollupColumn1Values = Array.Empty<string>(),
|
||||
rollupColumn2Values = Array.Empty<string>(),
|
||||
rollupColumn3Values = Array.Empty<string>(),
|
||||
groupByCategory = "CostDriver"
|
||||
};
|
||||
|
||||
// act
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, InitiativesEndpoint + "/set-filter-settings");
|
||||
await request.SetContentAsJsonAsync(FilterSettings);
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
|
||||
// assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
[Test, Order(4)]
|
||||
public async Task TestInitiativesExport_Step4()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, InitiativesEndpoint);
|
||||
await request.SetContentAsJsonAsync(FilterSettings);
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
|
||||
// act
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
[Test, Order(5)]
|
||||
public async Task TestInitiativesExport_Step5()
|
||||
{
|
||||
// arrange
|
||||
var data = new
|
||||
{
|
||||
sortOptions = new
|
||||
{
|
||||
sortField = "name",
|
||||
sortOrder = "Asc"
|
||||
},
|
||||
filters = new
|
||||
{
|
||||
ConfigurationGuid,
|
||||
name = "",
|
||||
status = 0,
|
||||
costDrivers = Array.Empty<string>(),
|
||||
costLeaders = Array.Empty<string>(),
|
||||
owners = Array.Empty<string>(),
|
||||
executiveSponsors = Array.Empty<string>(),
|
||||
workstreams = new string[] { Workstream },
|
||||
rollupColumn1Values = Array.Empty<string>(),
|
||||
rollupColumn2Values = Array.Empty<string>(),
|
||||
rollupColumn3Values = Array.Empty<string>(),
|
||||
groupByCategory = "CostDriver"
|
||||
}
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, InitiativesEndpoint + "/export");
|
||||
await request.SetContentAsJsonAsync(data);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// assert
|
||||
var headers = response.Content.Headers.Where(x => x.Value != null)
|
||||
.ToDictionary(k => k.Key, v => v.Value);
|
||||
var disposition = headers["Content-Disposition"].First();
|
||||
var regex = new Regex("attachment; filename=Initiatives_[\\d]{2}-[\\d]{2}-[\\d]{4}\\.xlsx; filename\\*=UTF-8''Initiatives_[\\d]{2}-[\\d]{2}-[\\d]{4}\\.xlsx",
|
||||
RegexOptions.IgnoreCase);
|
||||
Assert.That(regex.IsMatch(disposition));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
using Strata.ApiCommunication.Http;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[TestFixture(Category = "Integration")]
|
||||
public class TestOpportunityController : ApiTestBase
|
||||
{
|
||||
[TestCaseSource(nameof(OpportunityControllerTestCases))]
|
||||
public async Task OpportunityControllerTest(string testName, string url, string sortField, object? filters, bool exportable)
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
sortField = sortField ?? "identifiedSavings";
|
||||
filters = filters ?? new
|
||||
{
|
||||
configurationGuid,
|
||||
opportunityTypes = Array.Empty<string>(),
|
||||
identifiedSavings = null as object,
|
||||
viewVisible = true,
|
||||
excludeInitiatives = false,
|
||||
opportunitySearch = ""
|
||||
};
|
||||
|
||||
var data = new
|
||||
{
|
||||
pagingOptions = new
|
||||
{
|
||||
sortField,
|
||||
sortOrder = "Desc",
|
||||
first = 0,
|
||||
rows = 25
|
||||
},
|
||||
filters,
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
||||
await request.SetContentAsJsonAsync(data);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// asert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
});
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(OpportunityControllerTestCases))]
|
||||
public async Task OpportunityControllerFilterTest(string testName, string url, string sortField, object? filters, bool exportable)
|
||||
{
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url + $"/{configurationGuid}/filter-options");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// asert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
});
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(OpportunityControllerTestCases))]
|
||||
public async Task OpportunityControllerFilteExportTest(string testName, string url, string sortField, object? filters, bool exportable)
|
||||
{
|
||||
if (!exportable) { Assert.Ignore(); return; }
|
||||
// arrange
|
||||
var configurations = await GetConfigurations();
|
||||
var configuration = configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
var configurationGuid = configuration.ConfigurationGuid;
|
||||
sortField = sortField ?? "identifiedSavings";
|
||||
filters = filters ?? new
|
||||
{
|
||||
configurationGuid,
|
||||
opportunityTypes = Array.Empty<string>(),
|
||||
identifiedSavings = null as object,
|
||||
viewVisible = true,
|
||||
excludeInitiatives = false,
|
||||
opportunitySearch = ""
|
||||
};
|
||||
|
||||
var data = new
|
||||
{
|
||||
pagingOptions = new
|
||||
{
|
||||
sortField,
|
||||
sortOrder = "Desc",
|
||||
first = 0,
|
||||
rows = 25
|
||||
},
|
||||
filters,
|
||||
};
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, url + $"/export");
|
||||
await request.SetContentAsJsonAsync(data);
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request, CancellationToken.None);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// asert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid(exportable);
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> OpportunityControllerTestCases()
|
||||
{
|
||||
yield return new TestCaseData("all opportunities", "/api/v1/all-opportunities", null, new
|
||||
{
|
||||
configurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988"
|
||||
}, true).SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("charge code opportunities", "/api/v1/charge-code-opps", null, new
|
||||
{
|
||||
configurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988",
|
||||
opportunityTypes = Array.Empty<string>(),
|
||||
identifiedSavings = null as object,
|
||||
viewVisible = true,
|
||||
excludeInitiatives = false,
|
||||
opportunitySearch = ""
|
||||
}, true).SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("encounter opportunities", "/api/v1/encounter-opportunities", null, null, true)
|
||||
.SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("free form opportunities", "/api/v1/free-form-opportunities", null, null, true)
|
||||
.SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("general ledger opportunities", "/api/v1/general-ledger-opportunities", null, null, true)
|
||||
.SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("payroll opportunities", "/api/v1/payroll-opportunities", null, null, true)
|
||||
.SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("qvi opportunities", "/api/v1/quality-variation-item-opportunities", null, null, true)
|
||||
.SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("qvi breakdowns", "/api/v1/quality-variation-item-breakdowns", "identifiedSavingsTotal", new
|
||||
{
|
||||
exportFiltered = false,
|
||||
configurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988",
|
||||
identifiedSavings = 0,
|
||||
breakdownIds = Array.Empty<string>(),
|
||||
qualityVariationCases = 0
|
||||
}, false).SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("qvi events", "/api/v1/quality-variation-item-events", "identifiedSavingsTotal", new
|
||||
{
|
||||
configurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988"
|
||||
}, false).SetName("{m} {0}");
|
||||
|
||||
yield return new TestCaseData("variation opportunities", "/api/v1/variation-opportunities", null, new
|
||||
{
|
||||
configurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988"
|
||||
}, true).SetName("{m} {0}");
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using Strata.ContinuousImprovement.Api.Test.Integration.Info;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture(Category = "Integration")]
|
||||
public class TestSecuirtyController : ApiTestBase
|
||||
{
|
||||
[Test]
|
||||
public async Task TestSecurityIdenties()
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "/api/v1/security/identities");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
var securityInfos = await response.Content.ReadFromJsonAsync<IEnumerable<SecurityInfo>>();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
Assert.That(securityInfos, Is.Not.Null.And.Not.Empty);
|
||||
Assert.That(securityInfos.Any(s => s.Title == "Administrator, CCI"), Is.True);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Api.Test.Integration.Tests
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture(Category = "Integration")]
|
||||
public class TestUsersController : ApiTestBase
|
||||
{
|
||||
protected const string UsersEndpoint = "api/v1/users";
|
||||
|
||||
[TestCaseSource(nameof(TestUserCases))]
|
||||
public async Task TestUsers(string testName, string url, bool hasCostLeader, bool hasAaronHooper)
|
||||
{
|
||||
// arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, UsersEndpoint + $"/{url}");
|
||||
|
||||
// act
|
||||
var response = await HttpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// assert
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
response.AssertIsValid();
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> TestUserCases()
|
||||
{
|
||||
yield return new TestCaseData("administrators", "administrators", true, false)
|
||||
.SetName("{m} - {0}");
|
||||
yield return new TestCaseData("cost leaders", "cost-leaders", true, false)
|
||||
.SetName("{m} - {0}");
|
||||
yield return new TestCaseData("executive sponsors", "executive-sponsors", true, false)
|
||||
.SetName("{m} - {0}");
|
||||
yield return new TestCaseData("owners", "owners", true, true)
|
||||
.SetName("{m} - {0}");
|
||||
yield return new TestCaseData("users", "users", true, true)
|
||||
.SetName("{m} - {0}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user