diff --git a/.gitignore b/.gitignore
index f400df3..9a4719a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
-.idea/
\ No newline at end of file
+.idea/
+*.DotSettings.user
\ No newline at end of file
diff --git a/CDK.Framework.sln b/CDK.Framework.sln
index 9736ca1..94bb075 100644
--- a/CDK.Framework.sln
+++ b/CDK.Framework.sln
@@ -35,6 +35,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2. CDK Modules", "2. CDK Mo
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F2C4D978-97A6-4451-AAD2-16EDCA158D97}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Tests.Route53", "Sagittaras.CDK.Tests.Route53\Sagittaras.CDK.Tests.Route53.csproj", "{64D45D92-6955-42FC-87CD-E1419FB1EA17}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Tests", "Sagittaras.CDK.Tests\Sagittaras.CDK.Tests.csproj", "{E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Testing", "3. Testing", "{3A01C380-5151-4039-A00C-A33687E00861}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing", "Sagittaras.CDK.Testing\Sagittaras.CDK.Testing.csproj", "{D753C559-6F75-4493-A5A3-00CD0727A2DC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing.Route53", "Sagittaras.CDK.Testing.Route53\Sagittaras.CDK.Testing.Route53.csproj", "{2C4B4454-A145-405E-85BC-F54B56EAC39B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing.KMS", "Sagittaras.CDK.Testing.KMS\Sagittaras.CDK.Testing.KMS.csproj", "{FF8FB1E8-9071-470E-A4F3-6C0CD27716F4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +63,12 @@ Global
{61F8F5CD-30FF-4019-AE9D-E1AD0DA55029} = {506BD5FC-1E9D-47D4-A609-F977EDF69184}
{272BA799-3674-4104-8E01-511E9EDA0198} = {506BD5FC-1E9D-47D4-A609-F977EDF69184}
{C8F37959-BCB7-43DC-9812-A5623E420923} = {506BD5FC-1E9D-47D4-A609-F977EDF69184}
+ {64D45D92-6955-42FC-87CD-E1419FB1EA17} = {F2C4D978-97A6-4451-AAD2-16EDCA158D97}
+ {E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF} = {F2C4D978-97A6-4451-AAD2-16EDCA158D97}
+ {3A01C380-5151-4039-A00C-A33687E00861} = {AEF441A3-E5F9-46D2-82B9-8EE105CC3274}
+ {D753C559-6F75-4493-A5A3-00CD0727A2DC} = {3A01C380-5151-4039-A00C-A33687E00861}
+ {2C4B4454-A145-405E-85BC-F54B56EAC39B} = {3A01C380-5151-4039-A00C-A33687E00861}
+ {FF8FB1E8-9071-470E-A4F3-6C0CD27716F4} = {3A01C380-5151-4039-A00C-A33687E00861}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{940EEEA3-A068-4793-A44A-D2FCE1143E49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -81,5 +99,25 @@ Global
{C8F37959-BCB7-43DC-9812-A5623E420923}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8F37959-BCB7-43DC-9812-A5623E420923}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8F37959-BCB7-43DC-9812-A5623E420923}.Release|Any CPU.Build.0 = Release|Any CPU
+ {64D45D92-6955-42FC-87CD-E1419FB1EA17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {64D45D92-6955-42FC-87CD-E1419FB1EA17}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {64D45D92-6955-42FC-87CD-E1419FB1EA17}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {64D45D92-6955-42FC-87CD-E1419FB1EA17}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E42AD3AD-DBF2-4A25-98CF-E8DA76B356AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D753C559-6F75-4493-A5A3-00CD0727A2DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D753C559-6F75-4493-A5A3-00CD0727A2DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D753C559-6F75-4493-A5A3-00CD0727A2DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D753C559-6F75-4493-A5A3-00CD0727A2DC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2C4B4454-A145-405E-85BC-F54B56EAC39B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2C4B4454-A145-405E-85BC-F54B56EAC39B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2C4B4454-A145-405E-85BC-F54B56EAC39B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2C4B4454-A145-405E-85BC-F54B56EAC39B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FF8FB1E8-9071-470E-A4F3-6C0CD27716F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FF8FB1E8-9071-470E-A4F3-6C0CD27716F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FF8FB1E8-9071-470E-A4F3-6C0CD27716F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FF8FB1E8-9071-470E-A4F3-6C0CD27716F4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/Sagittaras.CDK.Testing.KMS/AliasAssertion.cs b/Sagittaras.CDK.Testing.KMS/AliasAssertion.cs
new file mode 100644
index 0000000..f72810c
--- /dev/null
+++ b/Sagittaras.CDK.Testing.KMS/AliasAssertion.cs
@@ -0,0 +1,11 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.KMS;
+
+///
+/// Assertion for AWS::KMS::Alias.
+///
+public class AliasAssertion : ResourceAssertion
+{
+ public override string Type => "AWS::KMS::Alias";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.KMS/AliasProperties.cs b/Sagittaras.CDK.Testing.KMS/AliasProperties.cs
new file mode 100644
index 0000000..89a3825
--- /dev/null
+++ b/Sagittaras.CDK.Testing.KMS/AliasProperties.cs
@@ -0,0 +1,14 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.KMS;
+
+///
+/// Properties for AWS::KMS::Alias.
+///
+public class AliasProperties : ResourceProperties
+{
+ ///
+ /// Name of the key alias.
+ ///
+ public string? AliasName { get; set; }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.KMS/KeyAssertion.cs b/Sagittaras.CDK.Testing.KMS/KeyAssertion.cs
new file mode 100644
index 0000000..0022139
--- /dev/null
+++ b/Sagittaras.CDK.Testing.KMS/KeyAssertion.cs
@@ -0,0 +1,11 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.KMS;
+
+///
+/// Assertion for AWS::KMS::Key.
+///
+public class KeyAssertion : ResourceAssertion
+{
+ public override string Type => "AWS::KMS::Key";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.KMS/KeyProperties.cs b/Sagittaras.CDK.Testing.KMS/KeyProperties.cs
new file mode 100644
index 0000000..79e049f
--- /dev/null
+++ b/Sagittaras.CDK.Testing.KMS/KeyProperties.cs
@@ -0,0 +1,11 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.KMS;
+
+///
+/// Properties for AWS::KMS::Key.
+///
+public class KeyProperties : ResourceProperties
+{
+
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.KMS/Sagittaras.CDK.Testing.KMS.csproj b/Sagittaras.CDK.Testing.KMS/Sagittaras.CDK.Testing.KMS.csproj
new file mode 100644
index 0000000..07ffb8a
--- /dev/null
+++ b/Sagittaras.CDK.Testing.KMS/Sagittaras.CDK.Testing.KMS.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ enable
+ true
+ 1.0.0-preview-01
+ CDK KMS testing library
+ Sagittaras Games
+ https://github.com/sagittaras/cdk.framework
+ https://github.com/sagittaras/cdk.framework/blob/main/LICENSE
+ https://github.com/sagittaras/cdk.framework
+
+
+
+
+
+
+
diff --git a/Sagittaras.CDK.Testing.Route53/DnsSecAssertion.cs b/Sagittaras.CDK.Testing.Route53/DnsSecAssertion.cs
new file mode 100644
index 0000000..adb271a
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/DnsSecAssertion.cs
@@ -0,0 +1,12 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Assertion for Aws::Route53::DNSSEC.
+///
+public class DnsSecAssertion : ResourceAssertion
+{
+ ///
+ public override string Type => "AWS::Route53::DNSSEC";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/DnsSecDependency.cs b/Sagittaras.CDK.Testing.Route53/DnsSecDependency.cs
new file mode 100644
index 0000000..438f91d
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/DnsSecDependency.cs
@@ -0,0 +1,24 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Class defining DNS SEC dependency on Key Signing Key.
+///
+public class DnsSecDependency : ResourceDependency
+{
+ ///
+ ///
+ ///
+ /// Identification of KSK by its name.
+ public DnsSecDependency(string kskName)
+ {
+ With(new KeySigningKeyAssertion
+ {
+ Properties = new KeySigningKeyProperties
+ {
+ Name = kskName
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/DnsSecProperties.cs b/Sagittaras.CDK.Testing.Route53/DnsSecProperties.cs
new file mode 100644
index 0000000..e05e45a
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/DnsSecProperties.cs
@@ -0,0 +1,11 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Properties for AWS::Route53::DNSSEC.
+///
+public class DnsSecProperties : ResourceProperties
+{
+
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/HostedZoneAssertion.cs b/Sagittaras.CDK.Testing.Route53/HostedZoneAssertion.cs
new file mode 100644
index 0000000..5a56941
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/HostedZoneAssertion.cs
@@ -0,0 +1,12 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Assertion for AWS::Route53::HostedZone.
+///
+public class HostedZoneAssertion : ResourceAssertion
+{
+ ///
+ public override string Type => "AWS::Route53::HostedZone";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/HostedZoneProperties.cs b/Sagittaras.CDK.Testing.Route53/HostedZoneProperties.cs
new file mode 100644
index 0000000..b76ae79
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/HostedZoneProperties.cs
@@ -0,0 +1,23 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Properties describing the Hosted Zone in the CloudFormation template.
+///
+public class HostedZoneProperties : ResourceProperties
+{
+ private string? _name;
+
+ ///
+ /// Name of the hosted zone.
+ ///
+ ///
+ /// Automatically appends the trailing dot that is generated for CloudFormation template.
+ ///
+ public string? Name
+ {
+ get => _name;
+ set => _name = value?.TrimEnd('.') + ".";
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/KeySigningKeyAssertion.cs b/Sagittaras.CDK.Testing.Route53/KeySigningKeyAssertion.cs
new file mode 100644
index 0000000..e025e25
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/KeySigningKeyAssertion.cs
@@ -0,0 +1,12 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Assertion for AWS::Route53::KeySigningKey.
+///
+public class KeySigningKeyAssertion : ResourceAssertion
+{
+ ///
+ public override string Type => "AWS::Route53::KeySigningKey";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/KeySigningKeyProperties.cs b/Sagittaras.CDK.Testing.Route53/KeySigningKeyProperties.cs
new file mode 100644
index 0000000..9026501
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/KeySigningKeyProperties.cs
@@ -0,0 +1,19 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Properties for AWS::Route53::KeySigningKey.
+///
+public class KeySigningKeyProperties : ResourceProperties
+{
+ ///
+ /// Current status of the KSK.
+ ///
+ public string? Status { get; set; }
+
+ ///
+ /// Name of the KSK.
+ ///
+ public string? Name { get; set; }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/RecordSetAssertion.cs b/Sagittaras.CDK.Testing.Route53/RecordSetAssertion.cs
new file mode 100644
index 0000000..d44d3f2
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/RecordSetAssertion.cs
@@ -0,0 +1,12 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Assertion for AWS::Route53::RecordSet.
+///
+public class RecordSetAssertion : ResourceAssertion
+{
+ ///
+ public override string Type => "AWS::Route53::RecordSet";
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/RecordSetProperties.cs b/Sagittaras.CDK.Testing.Route53/RecordSetProperties.cs
new file mode 100644
index 0000000..018f4d5
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/RecordSetProperties.cs
@@ -0,0 +1,11 @@
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Route53;
+
+///
+/// Properties for AWS::Route53::RecordSet.
+///
+public class RecordSetProperties : ResourceProperties
+{
+
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing.Route53/Sagittaras.CDK.Testing.Route53.csproj b/Sagittaras.CDK.Testing.Route53/Sagittaras.CDK.Testing.Route53.csproj
new file mode 100644
index 0000000..1c1cdca
--- /dev/null
+++ b/Sagittaras.CDK.Testing.Route53/Sagittaras.CDK.Testing.Route53.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ enable
+ true
+ 1.0.0-preview-01
+ CDK Route53 test library
+ Sagittaras Games
+ https://github.com/sagittaras/cdk.framework
+ https://github.com/sagittaras/cdk.framework/blob/main/LICENSE
+ https://github.com/sagittaras/cdk.framework
+
+
+
+
+
+
+
diff --git a/Sagittaras.CDK.Testing/Extensions/TemplateAssertionExtension.cs b/Sagittaras.CDK.Testing/Extensions/TemplateAssertionExtension.cs
new file mode 100644
index 0000000..62af3f9
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Extensions/TemplateAssertionExtension.cs
@@ -0,0 +1,34 @@
+using Amazon.CDK.Assertions;
+using Sagittaras.CDK.Testing.Resources;
+
+namespace Sagittaras.CDK.Testing.Extensions;
+
+///
+/// Extends the assertion template from the CDK by custom assertion methods.
+///
+public static class TemplateAssertionExtension
+{
+ ///
+ /// Asserts that the template has a resource with the given description.
+ ///
+ ///
+ ///
+ ///
+ public static void Assert(this Template template, TResourceAssertion assertion)
+ where TResourceAssertion : IResourceAssertion
+ {
+ template.HasResource(assertion.Type, assertion.GetResourceDescription(template));
+ }
+
+ ///
+ /// Asserts that the template has a given number of resources of the given type.
+ ///
+ ///
+ ///
+ ///
+ public static void AssertCount(this Template template, int count)
+ where TResourceAssertion : IResourceAssertion, new()
+ {
+ template.ResourceCountIs(new TResourceAssertion().Type, count);
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/IResourceAssertion.cs b/Sagittaras.CDK.Testing/Resources/IResourceAssertion.cs
new file mode 100644
index 0000000..19e3582
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/IResourceAssertion.cs
@@ -0,0 +1,38 @@
+using Amazon.CDK.Assertions;
+
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Basic interface describing the assertion for AWS resource.
+///
+public interface IResourceAssertion
+{
+ ///
+ /// AWS Resource type.
+ ///
+ string Type { get; }
+
+ ///
+ /// Maps on which resources the current resource depends on.
+ ///
+ IResourceDependency? DependsOn { get; set; }
+
+ ///
+ /// Converts the resource description to a dictionary suitable for template assertion.
+ ///
+ ///
+ IDictionary GetResourceDescription(Template template);
+}
+
+///
+/// Extends the basic resource assertion with properties.
+///
+/// Type of the properties used for the resource.
+public interface IResourceAssertion : IResourceAssertion
+ where TProperties : IResourceProperties, new()
+{
+ ///
+ /// Properties that helps to identify the resource.
+ ///
+ TProperties? Properties { get; set; }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/IResourceDependency.cs b/Sagittaras.CDK.Testing/Resources/IResourceDependency.cs
new file mode 100644
index 0000000..e1ed116
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/IResourceDependency.cs
@@ -0,0 +1,25 @@
+using Amazon.CDK.Assertions;
+
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Helps to describe and resolve dependencies between resources.
+///
+public interface IResourceDependency
+{
+ ///
+ /// Assigns the given assertion to the dependency.
+ ///
+ ///
+ ///
+ ///
+ IResourceDependency With(TResourceAssertion assertion)
+ where TResourceAssertion : IResourceAssertion;
+
+ ///
+ /// Resolves the dependencies from the given template.
+ ///
+ ///
+ ///
+ IEnumerable Resolve(Template template);
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/IResourceProperties.cs b/Sagittaras.CDK.Testing/Resources/IResourceProperties.cs
new file mode 100644
index 0000000..2fad86c
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/IResourceProperties.cs
@@ -0,0 +1,13 @@
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Describes the properties of a resource.
+///
+public interface IResourceProperties
+{
+ ///
+ /// Converts the properties to a dictionary suitable for template assertion.
+ ///
+ ///
+ IDictionary ToDictionary();
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/ResourceAssertion.cs b/Sagittaras.CDK.Testing/Resources/ResourceAssertion.cs
new file mode 100644
index 0000000..57a04ca
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/ResourceAssertion.cs
@@ -0,0 +1,50 @@
+using System.Reflection;
+using Amazon.CDK.Assertions;
+
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Abstract implementation of .
+///
+public abstract class ResourceAssertion : IResourceAssertion
+ where TProperties : IResourceProperties, new()
+{
+ ///
+ public abstract string Type { get; }
+
+ ///
+ public IResourceDependency? DependsOn { get; set; }
+
+ ///
+ public TProperties? Properties { get; set; }
+
+ ///
+ /// Gets the property members of the derived class.
+ ///
+ private IEnumerable PropertyMembers => GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
+
+ ///
+ public IDictionary GetResourceDescription(Template template)
+ {
+ Dictionary description = new();
+ foreach (PropertyInfo member in PropertyMembers)
+ {
+ object? value = member.GetValue(this);
+ switch (value)
+ {
+ case null:
+ continue;
+ case IResourceProperties properties:
+ value = properties.ToDictionary();
+ break;
+ case IResourceDependency dependency:
+ value = dependency.Resolve(template);
+ break;
+ }
+
+ description.Add(member.Name, value);
+ }
+
+ return description;
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/ResourceDependency.cs b/Sagittaras.CDK.Testing/Resources/ResourceDependency.cs
new file mode 100644
index 0000000..aabe506
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/ResourceDependency.cs
@@ -0,0 +1,36 @@
+using Amazon.CDK.Assertions;
+
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Base implementation of the resource dependency.
+///
+public class ResourceDependency : IResourceDependency
+{
+ ///
+ /// List of assertions that needs to be resolved as dependencies.
+ ///
+ private readonly List _dependencies = new();
+
+ ///
+ public IResourceDependency With(TResourceAssertion assertion) where TResourceAssertion : IResourceAssertion
+ {
+ _dependencies.Add(assertion);
+ return this;
+ }
+
+ ///
+ public IEnumerable Resolve(Template template)
+ {
+ List resolved = new();
+ foreach (IResourceAssertion assertion in _dependencies)
+ {
+ IEnumerable resolvedIds = template.FindResources(assertion.Type, assertion.GetResourceDescription(template))
+ .Select(x => x.Key);
+
+ resolved.AddRange(resolvedIds);
+ }
+
+ return resolved.ToArray();
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Resources/ResourceProperties.cs b/Sagittaras.CDK.Testing/Resources/ResourceProperties.cs
new file mode 100644
index 0000000..e5bd247
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Resources/ResourceProperties.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+
+namespace Sagittaras.CDK.Testing.Resources;
+
+///
+/// Abstract implementation of that provides a default implementation of .
+///
+///
+/// The resource properties should be nullable types to exclude them from the dictionary.
+///
+public abstract class ResourceProperties : IResourceProperties
+{
+ ///
+ /// Gets all properties members of the class.
+ ///
+ private IEnumerable Properties => GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+ ///
+ public IDictionary ToDictionary()
+ {
+ Dictionary dict = new();
+ foreach (PropertyInfo property in Properties)
+ {
+ object? value = property.GetValue(this);
+ if (value is null)
+ {
+ continue;
+ }
+
+ dict[property.Name] = value;
+ }
+
+ return dict;
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Testing/Sagittaras.CDK.Testing.csproj b/Sagittaras.CDK.Testing/Sagittaras.CDK.Testing.csproj
new file mode 100644
index 0000000..2fc8a91
--- /dev/null
+++ b/Sagittaras.CDK.Testing/Sagittaras.CDK.Testing.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ enable
+ true
+ 1.0.0-preview-01
+ Core test library for AWS CDK
+ Sagittaras Games
+ https://github.com/sagittaras/cdk.framework
+ https://github.com/sagittaras/cdk.framework/blob/main/LICENSE
+ https://github.com/sagittaras/cdk.framework
+
+
+
+
+
+
+
diff --git a/Sagittaras.CDK.Tests.Route53/PublicHostedZoneTest.cs b/Sagittaras.CDK.Tests.Route53/PublicHostedZoneTest.cs
new file mode 100644
index 0000000..518284e
--- /dev/null
+++ b/Sagittaras.CDK.Tests.Route53/PublicHostedZoneTest.cs
@@ -0,0 +1,72 @@
+using Amazon.CDK;
+using Amazon.CDK.Assertions;
+using Sagittaras.CDK.Framework.Route53;
+using Sagittaras.CDK.Testing.Extensions;
+using Sagittaras.CDK.Testing.KMS;
+using Sagittaras.CDK.Testing.Resources;
+using Sagittaras.CDK.Testing.Route53;
+using Xunit;
+
+namespace Sagittaras.CDK.Tests.Route53;
+
+///
+/// Test creation of Public Hosted zone.
+///
+public class PublicHostedZoneTest : ConstructTest
+{
+ private const string Domain = "example.com";
+ private const string Comment = "";
+
+ ///
+ /// Tests basic usage of the factory for Hosted Zone.
+ ///
+ [Fact]
+ public void Test_BaseFactoryUsage()
+ {
+ new PublicHostedZoneFactory(Stack, Domain, Comment)
+ .Construct();
+
+ Template template = StackTemplate;
+ template.Assert(new HostedZoneAssertion
+ {
+ Properties = new HostedZoneProperties
+ {
+ Name = Domain
+ }
+ });
+ template.AssertCount(1);
+ template.AssertCount(0);
+ }
+
+ ///
+ /// Tests the creation of Hosted Zone with DNSSEC enabled.
+ ///
+ [Fact]
+ public void Test_DNSSEC()
+ {
+ new PublicHostedZoneFactory(Stack, Domain, Comment)
+ .WithDnsSec()
+ .Construct();
+
+ Template template = StackTemplate;
+ template.AssertCount(1);
+ template.Assert(new AliasAssertion
+ {
+ Properties = new AliasProperties
+ {
+ AliasName = "alias/examplecom-key"
+ }
+ });
+ template.Assert(new KeySigningKeyAssertion
+ {
+ Properties = new KeySigningKeyProperties
+ {
+ Status = "ACTIVE"
+ }
+ });
+ template.Assert(new DnsSecAssertion
+ {
+ DependsOn = new DnsSecDependency("examplecom")
+ });
+ }
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Tests.Route53/Sagittaras.CDK.Tests.Route53.csproj b/Sagittaras.CDK.Tests.Route53/Sagittaras.CDK.Tests.Route53.csproj
new file mode 100644
index 0000000..37f999a
--- /dev/null
+++ b/Sagittaras.CDK.Tests.Route53/Sagittaras.CDK.Tests.Route53.csproj
@@ -0,0 +1,32 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Sagittaras.CDK.Tests/ConstructTest.cs b/Sagittaras.CDK.Tests/ConstructTest.cs
new file mode 100644
index 0000000..2147478
--- /dev/null
+++ b/Sagittaras.CDK.Tests/ConstructTest.cs
@@ -0,0 +1,31 @@
+using Amazon.CDK;
+using Amazon.CDK.Assertions;
+
+namespace Sagittaras.CDK.Tests;
+
+///
+/// Base class for easier writing of tests for constructs.
+///
+public abstract class ConstructTest
+{
+ protected ConstructTest()
+ {
+ App = new App();
+ Stack = new Stack(App);
+ }
+
+ ///
+ /// Instance of App under which the stack is defined.
+ ///
+ protected App App { get; }
+
+ ///
+ /// Instance of stack to which the constructs within the test can be assigned.
+ ///
+ protected Stack Stack { get; }
+
+ ///
+ /// Creates a new instance of Assertion Template from current stack state.
+ ///
+ protected Template StackTemplate => Template.FromStack(Stack);
+}
\ No newline at end of file
diff --git a/Sagittaras.CDK.Tests/Sagittaras.CDK.Tests.csproj b/Sagittaras.CDK.Tests/Sagittaras.CDK.Tests.csproj
new file mode 100644
index 0000000..e0d3630
--- /dev/null
+++ b/Sagittaras.CDK.Tests/Sagittaras.CDK.Tests.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+