From 104187fcac64ec99719029ce0bd0d0d893721a87 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Thu, 27 Feb 2025 17:24:58 +0100 Subject: [PATCH] Adds LightBDD --- Database/Core/DCL/SetupDbAdmin.cs | 139 +++++++----------- .../FeatureFixtures/UserRegistrationSpecs.cs | 73 +++++++++ PlanTempus.X.BDD/LightBddIntegration.cs | 29 ++++ PlanTempus.X.BDD/PlanTempus.X.BDD.csproj | 43 ++++++ .../Scenarios/UserRegistrationSpecs.cs | 21 +++ PlanTempus.sln | 8 +- .../.dbeaver/.credentials-config.json.bak | Bin 128 -> 224 bytes SqlManagement/.dbeaver/.data-sources.json.bak | 37 ++++- .../.dbeaver/credentials-config.json | Bin 224 -> 224 bytes SqlManagement/.dbeaver/data-sources.json | 5 +- SqlManagement/.dbeaver/project-metadata.json | 2 +- Tests/CodeSnippets/sandbox.sql | 11 ++ .../JsonConfigurationProviderTests.cs | 18 +-- .../SmartConfigProviderTests.cs | 112 +++++++------- .../appconfiguration.dev.json | 2 +- ...s.Tests.csproj => PlanTempus.X.TDD.csproj} | 2 +- 16 files changed, 344 insertions(+), 158 deletions(-) create mode 100644 PlanTempus.X.BDD/FeatureFixtures/UserRegistrationSpecs.cs create mode 100644 PlanTempus.X.BDD/LightBddIntegration.cs create mode 100644 PlanTempus.X.BDD/PlanTempus.X.BDD.csproj create mode 100644 PlanTempus.X.BDD/Scenarios/UserRegistrationSpecs.cs create mode 100644 Tests/CodeSnippets/sandbox.sql rename Tests/{PlanTempus.Tests.csproj => PlanTempus.X.TDD.csproj} (95%) diff --git a/Database/Core/DCL/SetupDbAdmin.cs b/Database/Core/DCL/SetupDbAdmin.cs index 989595b..07fcce1 100644 --- a/Database/Core/DCL/SetupDbAdmin.cs +++ b/Database/Core/DCL/SetupDbAdmin.cs @@ -7,109 +7,84 @@ using PlanTempus.Database.Core.ConnectionFactory; namespace PlanTempus.Database.Core.DCL { - /// - /// Only a superadmin or similar can create Application Users - /// - public class SetupDbAdmin : IDbConfigure - { - public class Command - { - public required string Schema { get; init; } - public required string User { get; init; } - public required string Password { get; init; } - } + /// + /// Only a superadmin or similar can create Application Users + /// + public class SetupDbAdmin : IDbConfigure + { + public class Command + { + public required string Schema { get; init; } + public required string User { get; init; } + public required string Password { get; init; } + } - Command _command; - private readonly IDbConnectionFactory _connectionFactory; + Command _command; + private readonly IDbConnectionFactory _connectionFactory; - public SetupDbAdmin(IDbConnectionFactory connectionFactory) - { - _connectionFactory = connectionFactory; - } + public SetupDbAdmin(IDbConnectionFactory connectionFactory) + { + _connectionFactory = connectionFactory; + } - public void With(Command command, ConnectionStringParameters parameters = null) - { - _command = command; + public void With(Command command, ConnectionStringParameters parameters = null) + { + _command = command; - if (!Validations.IsValidSchemaName(_command.Schema)) - throw new ArgumentException("Invalid schema name", _command.Schema); + if (!Validations.IsValidSchemaName(_command.Schema)) + throw new ArgumentException("Invalid schema name", _command.Schema); - using var conn = parameters is null ? _connectionFactory.Create() : _connectionFactory.Create(parameters); - using var transaction = conn.OpenWithTransaction(); - try - { - CreateSchema(conn); - CreateRole(conn); - GrantSchemaRights(conn); + using var conn = parameters is null ? _connectionFactory.Create() : _connectionFactory.Create(parameters); + using var transaction = conn.OpenWithTransaction(); + try + { + CreateSchema(conn); + CreateRole(conn); + GrantSchemaRights(conn); - transaction.Commit(); - } - catch (Exception ex) - { - transaction.Rollback(); - throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex); - } + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex); + } - } + } - private void CreateSchema(IDbConnection db) - { - var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; - db.ExecuteSql(sql); - } + private void CreateSchema(IDbConnection db) + { + var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; + db.ExecuteSql(sql); + } - private void CreateRole(IDbConnection db) - { - var sql = $@" + private void CreateRole(IDbConnection db) + { + var sql = $@" DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{_command.User}') THEN CREATE ROLE {_command.User} WITH CREATEDB CREATEROLE LOGIN PASSWORD '{_command.Password}'; END IF; END $$;"; - db.ExecuteSql(sql); + db.ExecuteSql(sql); - var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; - db.ExecuteSql(sql1); + var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; + db.ExecuteSql(sql1); - var sql2 = $"ALTER SCHEMA {_command.Schema} OWNER TO {_command.User};"; - db.ExecuteSql(sql2); + var sql2 = $"ALTER SCHEMA {_command.Schema} OWNER TO {_command.User};"; + db.ExecuteSql(sql2); - } + } - private void GrantSchemaRights(IDbConnection db) - { - // Grant USAGE og alle CREATE rettigheder på schema niveau - //GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User}; - var sql = $@"GRANT CREATE ON SCHEMA {_command.Schema} TO {_command.User};"; + private void GrantSchemaRights(IDbConnection db) + { + var sql = $@"GRANT CREATE ON SCHEMA {_command.Schema} TO {_command.User};"; - db.ExecuteSql(sql); + db.ExecuteSql(sql); - // Grant rettigheder på eksisterende og fremtidige tabeller - //var sql1 = $"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {_command.Schema} TO {_command.User};"; - //ExecuteSql(sql1); - - //var sql2 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT ALL PRIVILEGES ON TABLES TO {_command.User};"; - //ExecuteSql(sql2); - - //// Grant sequence rettigheder - //var sql3 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; - //ExecuteSql(sql3); - - //// Grant execute på functions - //var sql4 = $"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA {_command.Schema} TO {_command.User};"; - //ExecuteSql(sql4); - - //// Grant for fremtidige functions - //var sql5 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT EXECUTE ON FUNCTIONS TO {_command.User};"; - //ExecuteSql(sql5); - - //// Grant for fremtidige sequences - //var sql6 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT USAGE ON SEQUENCES TO {_command.User};"; - //ExecuteSql(sql6); - } - - } + } + } } diff --git a/PlanTempus.X.BDD/FeatureFixtures/UserRegistrationSpecs.cs b/PlanTempus.X.BDD/FeatureFixtures/UserRegistrationSpecs.cs new file mode 100644 index 0000000..1876a58 --- /dev/null +++ b/PlanTempus.X.BDD/FeatureFixtures/UserRegistrationSpecs.cs @@ -0,0 +1,73 @@ +using LightBDD.Framework; +using LightBDD.Framework.Scenarios; +using LightBDD.MsTest3; +using Shouldly; + +namespace PlanTempus.X.BDD.FeatureFixtures; +[TestClass] +public partial class UserRegistrationSpecs : FeatureFixture +{ + //private CalculatorContext _context; + + public UserRegistrationSpecs() + { + //_context = new CalculatorContext(); + } + //[Scenario] + //[TestMethod] + //public void Successful_user_registration_with_valid_email() + //{ + // // Runner.RunScenario( + // // _ => Given_no_user_exists_with_email("test@example.com") + + // //); + // //await Runner.RunScenarioAsync( + // // _ => Given_no_user_exists_with_email("test@example.com"), + // // _ => When_I_submit_registration_with_name_and_email("Test User", "test@example.com"), + // // _ => Then_a_new_user_should_be_created_with_email_and_confirmation_status("test@example.com", false), + // // _ => Then_a_confirmation_email_should_be_sent() + // //); + //} + protected async Task Given_no_user_exists_with_email(string email) + { + await Task.Run(() => + { + + }); + //Assert.IsFalse(await _context.UserExistsAsync(email), $"User with email {email} should not exist"); + true.ShouldBe(true); + } + + protected async Task When_I_submit_registration_with_name_and_email(string name, string email) + { + //await _context.RegisterUserAsync(name, email); + await Task.Run(() => + { + + }); + true.ShouldBe(true); + } + + protected async Task Then_a_new_user_should_be_created_with_email_and_confirmation_status(string email, bool emailConfirmed) + { + //var user = await _context.GetUserByEmailAsync(email); + //Assert.IsNotNull(user); + //Assert.AreEqual(email, user.Email); + //Assert.AreEqual(emailConfirmed, user.EmailConfirmed); + await Task.Run(() => + { + + }); + true.ShouldBe(true); + } + + protected async Task Then_a_confirmation_email_should_be_sent() + { + //Assert.IsTrue(await _context.WasConfirmationEmailSentAsync(), "Confirmation email should be sent"); + await Task.Run(() => + { + + }); + true.ShouldBe(true); + } +} \ No newline at end of file diff --git a/PlanTempus.X.BDD/LightBddIntegration.cs b/PlanTempus.X.BDD/LightBddIntegration.cs new file mode 100644 index 0000000..22d93a9 --- /dev/null +++ b/PlanTempus.X.BDD/LightBddIntegration.cs @@ -0,0 +1,29 @@ +using LightBDD.Core.Configuration; +using LightBDD.Framework.Configuration; +using LightBDD.Framework.Reporting.Formatters; +using LightBDD.MsTest3; + +namespace PlanTempus.X.BDD +{ + [TestClass] + public class LightBddIntegration + { + [AssemblyInitialize] + public static void Setup(TestContext testContext) { LightBddScope.Initialize(OnConfigure); } + [AssemblyCleanup] + public static void Cleanup() { LightBddScope.Cleanup(); } + + /// + /// This method allows to customize LightBDD behavior. + /// The code below configures LightBDD to produce also a plain text report after all tests are done. + /// More information on what can be customized can be found on wiki: https://github.com/LightBDD/LightBDD/wiki/LightBDD-Configuration#configurable-lightbdd-features + /// + private static void OnConfigure(LightBddConfiguration configuration) + { + configuration + .ReportWritersConfiguration() + .AddFileWriter("~\\Reports\\FeaturesReport.html"); + + } + } +} diff --git a/PlanTempus.X.BDD/PlanTempus.X.BDD.csproj b/PlanTempus.X.BDD/PlanTempus.X.BDD.csproj new file mode 100644 index 0000000..8844c36 --- /dev/null +++ b/PlanTempus.X.BDD/PlanTempus.X.BDD.csproj @@ -0,0 +1,43 @@ + + + + net8.0 + enable + + false + true + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + + diff --git a/PlanTempus.X.BDD/Scenarios/UserRegistrationSpecs.cs b/PlanTempus.X.BDD/Scenarios/UserRegistrationSpecs.cs new file mode 100644 index 0000000..4e111b7 --- /dev/null +++ b/PlanTempus.X.BDD/Scenarios/UserRegistrationSpecs.cs @@ -0,0 +1,21 @@ +using LightBDD.Framework; +using LightBDD.Framework.Scenarios; +using LightBDD.MsTest3; + +namespace PlanTempus.X.BDD.Scenarios; + +[TestClass] +public partial class UserRegistrationSpecs : FeatureFixtures.UserRegistrationSpecs +{ + [Scenario] + [TestMethod] + public async Task Successful_user_registration_with_valid_email() + { + await Runner.RunScenarioAsync( + _ => Given_no_user_exists_with_email("test@example.com"), + _ => When_I_submit_registration_with_name_and_email("Test User", "test@example.com"), + _ => Then_a_new_user_should_be_created_with_email_and_confirmation_status("test@example.com", false), + _ => Then_a_confirmation_email_should_be_sent() + ); + } +} diff --git a/PlanTempus.sln b/PlanTempus.sln index 5138f3d..dc63cfc 100644 --- a/PlanTempus.sln +++ b/PlanTempus.sln @@ -4,7 +4,7 @@ VisualStudioVersion = 17.10.35013.160 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Core", "Core\PlanTempus.Core.csproj", "{7B554252-1CE4-44BD-B108-B0BDCCB24742}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Tests", "Tests\PlanTempus.Tests.csproj", "{85614050-CFB0-4E39-81D3-7D99946449D9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.X.TDD", "Tests\PlanTempus.X.TDD.csproj", "{85614050-CFB0-4E39-81D3-7D99946449D9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Application", "Application\PlanTempus.Application.csproj", "{111CE8AE-E637-4376-A5A3-88D33E77EA88}" EndProject @@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.Database", "Data EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlanTempus.SetupInfrastructure", "SetupInfrastructure\PlanTempus.SetupInfrastructure.csproj", "{48300227-BCBB-45A3-8359-9064DA85B1F9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlanTempus.X.BDD", "PlanTempus.X.BDD\PlanTempus.X.BDD.csproj", "{8CA2246B-7D8C-40DA-9042-CA17A7A7672B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,6 +32,10 @@ Global {111CE8AE-E637-4376-A5A3-88D33E77EA88}.Debug|Any CPU.Build.0 = Debug|Any CPU {111CE8AE-E637-4376-A5A3-88D33E77EA88}.Release|Any CPU.ActiveCfg = Release|Any CPU {111CE8AE-E637-4376-A5A3-88D33E77EA88}.Release|Any CPU.Build.0 = Release|Any CPU + {8CA2246B-7D8C-40DA-9042-CA17A7A7672B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CA2246B-7D8C-40DA-9042-CA17A7A7672B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CA2246B-7D8C-40DA-9042-CA17A7A7672B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CA2246B-7D8C-40DA-9042-CA17A7A7672B}.Release|Any CPU.Build.0 = Release|Any CPU {D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}.Debug|Any CPU.Build.0 = Debug|Any CPU {D5096A7F-E6D4-4C87-874E-2D9A6BEAD57F}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/SqlManagement/.dbeaver/.credentials-config.json.bak b/SqlManagement/.dbeaver/.credentials-config.json.bak index 01ccc39b1537d77f2f1b585352dc1367f52ae040..36d53d03f2980574128a525d718f4a4eef53a843 100644 GIT binary patch literal 224 zcmV<603ZM7!l4Hv_|Hlnab+;`d@o`M>TgRdFFjKEX&Iu zBG2Xyq|RJL;r=CdabS50(SmxmgdTF~Pn&4M{JPUhal4I%IiI2@F2G2H0by&D;H2|x z8dCwR|0Sak3lryf7>EX9CA-gtoef>qn47B$Of*%qGDpWc-{B{)248+-(Sg1nJ}405 aHwq$BF7a-!**(pJY@%294n8qPq%nI{lV@H4 literal 128 zcmV-`0Du4YokuMl!$RAly?TzJq)PQ*zVJYqxAfVN1HDYXS{frXOGuf|Y&GB&J-es3 zYyc@`KW1ZGJZ<&kAwBU)8F2j)W3UlZDxH~{7M}nN?lId60!TFmeZ1_I6F)L diff --git a/SqlManagement/.dbeaver/.data-sources.json.bak b/SqlManagement/.dbeaver/.data-sources.json.bak index 46e1081..6cd4a80 100644 --- a/SqlManagement/.dbeaver/.data-sources.json.bak +++ b/SqlManagement/.dbeaver/.data-sources.json.bak @@ -33,9 +33,40 @@ "postgresql.dd.tag.string": "false" }, "auth-model": "native" - }, - "custom-properties": { - "SQLEditor.outputPanel.autoShow": "false" + } + }, + "postgres-jdbc-195383ce5c3-68a4eee43daef302": { + "provider": "postgresql", + "driver": "postgres-jdbc", + "name": "UB-KK01-postgres 1", + "save-password": true, + "configuration": { + "host": "192.168.1.57", + "port": "5432", + "database": "ptmain", + "url": "jdbc:postgresql://192.168.1.57:5432/ptmain", + "configurationType": "MANUAL", + "home": "postgresql_client", + "type": "dev", + "closeIdleConnection": true, + "properties": { + "connectTimeout": "20", + "loginTimeout": "20", + "escapeSyntaxCallMode": "callIfNoReturn" + }, + "provider-properties": { + "@dbeaver-show-non-default-db@": "true", + "@dbeaver-chosen-role@": "", + "@dbeaver-show-template-db@": "false", + "@dbeaver-show-unavailable-db@": "false", + "show-database-statistics": "false", + "@dbeaver-read-all-data-types-db@": "false", + "read-keys-with-columns": "false", + "@dbeaver-use-prepared-statements-db@": "false", + "postgresql.dd.plain.string": "false", + "postgresql.dd.tag.string": "false" + }, + "auth-model": "native" } } }, diff --git a/SqlManagement/.dbeaver/credentials-config.json b/SqlManagement/.dbeaver/credentials-config.json index 078ce164b62fefb467c426ae6f0bea4116f1d303..b0c18fcd77c412fee69d23ce70d648c3fedf0459 100644 GIT binary patch literal 224 zcmV<603ZMGpg=UyVT2(POZ$zTjraVUl3aL#d7MjlskYUNEb;|su+8i7SYL%KR0L<9CO z504*U&O!zx0zb5G2Gd1|Yf=2J?v>yL_x6$2e22fF^6Ub% z5}dL_!8`4+W+LcDa;N$u$j zs^!cpV=z~#*!sTo&p;17LGMG*z;B~ty}V5g0!FBRtA$p9(?mRz(5G_ToMc6Hh)!=% a!#rX&m3H-l0R0@CF(puM5&wBxuIg^mG;?|Y diff --git a/SqlManagement/.dbeaver/data-sources.json b/SqlManagement/.dbeaver/data-sources.json index 5e6aa2e..50c2222 100644 --- a/SqlManagement/.dbeaver/data-sources.json +++ b/SqlManagement/.dbeaver/data-sources.json @@ -33,12 +33,9 @@ "postgresql.dd.tag.string": "false" }, "auth-model": "native" - }, - "custom-properties": { - "SQLEditor.outputPanel.autoShow": "false" } }, - "postgres-jdbc-1950174dc2f-6bd6c7100db1cc5c": { + "postgres-jdbc-195383ce5c3-68a4eee43daef302": { "provider": "postgresql", "driver": "postgres-jdbc", "name": "UB-KK01-sathumper", diff --git a/SqlManagement/.dbeaver/project-metadata.json b/SqlManagement/.dbeaver/project-metadata.json index 3200961..525a28a 100644 --- a/SqlManagement/.dbeaver/project-metadata.json +++ b/SqlManagement/.dbeaver/project-metadata.json @@ -1 +1 @@ -{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}} \ No newline at end of file +{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-schema":"system","default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"sandbox"}}} \ No newline at end of file diff --git a/Tests/CodeSnippets/sandbox.sql b/Tests/CodeSnippets/sandbox.sql new file mode 100644 index 0000000..7db0508 --- /dev/null +++ b/Tests/CodeSnippets/sandbox.sql @@ -0,0 +1,11 @@ +INSERT INTO "system".app_configuration ("key",value,"label",content_type,valid_from,expires_at,created_at,modified_at,etag) VALUES + ('Email:Templates:Welcome','{"subject":"Velkommen til vores platform","template":"welcome-dk.html","sender":"velkommen@firma.dk"}','test','application/json','2024-01-01 01:00:00+01',NULL,'2025-02-03 16:46:36.665888+01','2025-02-03 16:47:30.528326+01','c48949c4-c02f-4c77-b81c-e281a810def1'::uuid), + ('Email:Templates:Password','{"subject":"Nulstil dit kodeord","template":"reset-password-dk.html","sender":"support@firma.dk"}','Email Templates','application/json','2024-01-01 01:00:00+01',NULL,'2025-02-03 16:47:56.537775+01','2025-02-03 16:47:56.537775+01','26500738-4f5b-4cc8-a0e4-2a6a5fd57675'::uuid), + ('Debug','true',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','f1348731-9396-4f1d-b40a-7fbd23a897d2'::uuid), + ('Database:ConnectionString','"Server=db.example.com;Port=5432"',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','2aa0bc3e-fa24-449a-8f25-a76d9b4d535e'::uuid), + ('Database:Timeout','30',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','d25ebb14-49f6-4e33-9ac7-a3253705d0fb'::uuid), + ('Database:UseSSL','true',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','f4d52ec4-b723-4561-9b18-0e7a68b89a17'::uuid), + ('Logging:FileOptions','{"Path": "/var/logs/app.log", "MaxSizeMB": 100, "RetentionDays": 7}',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','06c0891d-a860-4acc-917a-d0877f511c1b'::uuid), + ('Features:Experimental','{"Enabled": true, "RolloutPercentage": 25, "AllowedUserGroups": ["beta"]}',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','0136fdef-51d9-4909-82ef-f72053ce6d6d'::uuid), + ('API:Endpoints','"/api/users"',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','fe362b69-a486-48ad-9165-2e623e2e6f70'::uuid), + ('API:Endpoints','"/api/products"',NULL,'text/plain',NULL,NULL,'2025-02-02 14:25:22.200058+01','2025-02-02 14:25:22.200058+01','c087e2d4-1f38-4814-b4dd-f30c463dc6d1'::uuid); diff --git a/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs b/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs index 53e5b2e..8ae0689 100644 --- a/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs +++ b/Tests/ConfigurationTests/JsonConfigurationProviderTests.cs @@ -1,5 +1,5 @@ -using FluentAssertions; using Newtonsoft.Json.Linq; +using Shouldly; using PlanTempus.Tests; using PlanTempus.Core.Configurations; using PlanTempus.Core.Configurations.JsonConfigProvider; @@ -33,8 +33,8 @@ namespace PlanTempus.Tests.ConfigurationTests var section = builder.GetSection("Feature"); // Assert - section.Should().NotBeNull(); - section.Value.Should().BeEquivalentTo(expectedJObject); + section.ShouldNotBeNull(); + section.Value.ShouldBeEquivalentTo(expectedJObject); } [TestMethod] @@ -58,8 +58,8 @@ namespace PlanTempus.Tests.ConfigurationTests var actualFeatureObsoleted = builder.GetSection("Feature").Get(); #pragma warning restore CS0618 // Type or member is obsolete // Assert - actualFeature.Should().BeEquivalentTo(expectedFeature); - actualFeatureObsoleted.Should().BeEquivalentTo(expectedFeature); + actualFeature.ShouldBeEquivalentTo(expectedFeature); + actualFeatureObsoleted.ShouldBeEquivalentTo(expectedFeature); } [TestMethod] @@ -76,7 +76,7 @@ namespace PlanTempus.Tests.ConfigurationTests var actualFeature = builder.GetSection("AnotherSetting").Get("Thresholds:High"); // Assert - actualFeature.Should().BeEquivalentTo(expectedFeature); + actualFeature.ShouldBeEquivalentTo(expectedFeature); } /// /// Testing a stupid indexer for compability with Microsoft ConfigurationBuilder @@ -95,7 +95,7 @@ namespace PlanTempus.Tests.ConfigurationTests var actual = builder["Authentication"]; // Assert - actual.Should().BeEquivalentTo(expected); + actual.ShouldBeEquivalentTo(expected); } [TestMethod] public void Get_ShouldReturnCorrectValueAsInt() @@ -111,7 +111,7 @@ namespace PlanTempus.Tests.ConfigurationTests var actualFeature = builder.GetSection("AnotherSetting:Temperature").Get("Indoor:Max:Limit"); // Assert - actualFeature.Should().Be(expectedFeature); + actualFeature.ShouldBe(expectedFeature); } [TestMethod] public void Get_ShouldReturnCorrectValueAsBool() @@ -128,7 +128,7 @@ namespace PlanTempus.Tests.ConfigurationTests var actualFeature = configRoot.Get("Database:UseSSL"); // Assert - actualFeature.Should().Be(expectedFeature); + actualFeature.ShouldBe(expectedFeature); } } diff --git a/Tests/ConfigurationTests/SmartConfigProviderTests.cs b/Tests/ConfigurationTests/SmartConfigProviderTests.cs index 225e695..2ab1df2 100644 --- a/Tests/ConfigurationTests/SmartConfigProviderTests.cs +++ b/Tests/ConfigurationTests/SmartConfigProviderTests.cs @@ -1,5 +1,5 @@ -using FluentAssertions; -using Autofac; +using Autofac; +using Shouldly; using System.Data; using Insight.Database; using Npgsql; @@ -10,78 +10,78 @@ using PlanTempus.Core.Configurations.SmartConfigProvider; namespace PlanTempus.Tests.ConfigurationTests { - [TestClass] - public class SmartConfigProviderTests : TestFixture - { + [TestClass] + public class SmartConfigProviderTests : TestFixture + { + const string _testFolder = "ConfigurationTests/"; - [TestMethod] - public void TrySmartConfigWithOptionsForPostgres() - { - var config = new ConfigurationBuilder() - .AddJsonFile("appconfiguration.dev.json") - .AddSmartConfig(options => options.UsePostgres("DefaultConnection")) - .Build(); + [TestMethod] + public void TrySmartConfigWithOptionsForPostgres() + { + var config = new ConfigurationBuilder() + .AddJsonFile($"{_testFolder}appconfiguration.dev.json") + .AddSmartConfig(options => options.UsePostgres("DefaultConnection")) + .Build(); - var actualFeature = config.Get("Database:UseSSL"); + var actualFeature = config.Get("Database:UseSSL"); - } + } - [TestMethod] - public void Get_ShouldReturnCorrectValueAsBool() - { - // Arrange - var expectedFeature = true; + [TestMethod] + public void Get_ShouldReturnCorrectValueAsBool() + { + // Arrange + var expectedFeature = true; - var config = new ConfigurationBuilder() - .AddJsonFile("appconfiguration.dev.json") - .AddSmartConfig() - .Build(); + var config = new ConfigurationBuilder() + .AddJsonFile($"{_testFolder}appconfiguration.dev.json") + .AddSmartConfig(options => options.UsePostgres("DefaultConnection")) + .Build(); - // Act - var actualFeature = config.Get("Database:UseSSL"); + // Act + var actualFeature = config.Get("Database:UseSSL"); - // Assert - actualFeature.Should().Be(expectedFeature); - } - [TestMethod] - public void Get_ShouldReturnCorrectValueWhenSelectingIntoValueRowInConfigTable() - { - // Arrange - var expectedFeature = 100; + // Assert + actualFeature.ShouldBe(expectedFeature); + } + [TestMethod] + public void Get_ShouldReturnCorrectValueWhenSelectingIntoValueRowInConfigTable() + { + // Arrange + var expectedFeature = 100; - var builder = new ConfigurationBuilder() - .AddJsonFile("appconfiguration.dev.json") - .AddSmartConfig() - .Build(); + var builder = new ConfigurationBuilder() + .AddJsonFile($"{_testFolder}appconfiguration.dev.json") + .AddSmartConfig(options => options.UsePostgres("DefaultConnection")) + .Build(); - // Act - var actualFeature = builder.GetSection("Logging:FileOptions").Get("MaxSizeMB"); - var withoutSectionThisAlsoWorks = builder.Get("Logging:FileOptions:MaxSizeMB"); + // Act + var actualFeature = builder.GetSection("Logging:FileOptions").Get("MaxSizeMB"); + var withoutSectionThisAlsoWorks = builder.Get("Logging:FileOptions:MaxSizeMB"); - // Assert - actualFeature.Should().Be(expectedFeature); - actualFeature.Should().Be(withoutSectionThisAlsoWorks); + // Assert + actualFeature.ShouldBe(expectedFeature); + actualFeature.ShouldBe(withoutSectionThisAlsoWorks); - } + } - [TestMethod] - public void TryGetActiveConfigurations() - { + [TestMethod] + public void TryGetActiveConfigurations() + { + var connFactory = Container.Resolve(); - const string sql = @" + const string sql = @" SELECT id, ""key"", value, label, content_type, valid_from, expires_at, created_at, modified_at, etag FROM app_configuration WHERE CURRENT_TIMESTAMP BETWEEN valid_from AND expires_at OR (valid_from IS NULL AND expires_at IS NULL)"; - var conn = Container.Resolve(); - - var result = conn.QuerySql(sql); - - } - } - - + using (var conn = connFactory.Create()) + { + var result = conn.QuerySql(sql); + } + } + } } \ No newline at end of file diff --git a/Tests/ConfigurationTests/appconfiguration.dev.json b/Tests/ConfigurationTests/appconfiguration.dev.json index 9fe57de..1600409 100644 --- a/Tests/ConfigurationTests/appconfiguration.dev.json +++ b/Tests/ConfigurationTests/appconfiguration.dev.json @@ -1,7 +1,7 @@ { "AllowedHosts": "*", "ConnectionStrings": { - "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id=sathumper;Password=3911;" + "DefaultConnection": "Host=192.168.1.57;Port=5432;Database=sandbox;User Id=sathumper;Password=3911;" }, "ApplicationInsights": { "ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548", diff --git a/Tests/PlanTempus.Tests.csproj b/Tests/PlanTempus.X.TDD.csproj similarity index 95% rename from Tests/PlanTempus.Tests.csproj rename to Tests/PlanTempus.X.TDD.csproj index e5a1cc2..396e620 100644 --- a/Tests/PlanTempus.Tests.csproj +++ b/Tests/PlanTempus.X.TDD.csproj @@ -10,11 +10,11 @@ - +