diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ed63bb2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,42 @@ +root = true + +[*] +indent_style = space +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.cs] +indent_size = 4 + +[*.{csproj,props,targets,nuspec,resx}] +indent_size = 2 + +[*.{json,yml,yaml}] +indent_size = 2 + +[*.{md,sql}] +trim_trailing_whitespace = false + +[*.cs] +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_style_namespace_declarations = file_scoped:suggestion +csharp_using_directive_placement = outside_namespace:suggestion + +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +dotnet_diagnostic.CA1001.severity = warning +dotnet_diagnostic.CA1051.severity = warning +dotnet_diagnostic.CA1816.severity = warning +dotnet_diagnostic.CA2227.severity = warning diff --git a/.gitignore b/.gitignore index af2a9f3..1e10283 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ Content/ tiles/ ready/ .DS_Store +TestResults/ +coverage.cobertura.xml +coverage.opencover.xml +*.coverage diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..c428384 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,10 @@ + + + + true + latest + None + false + + + diff --git a/SatelliteProvider.Tests/ToolingConfigurationTests.cs b/SatelliteProvider.Tests/ToolingConfigurationTests.cs new file mode 100644 index 0000000..a371aba --- /dev/null +++ b/SatelliteProvider.Tests/ToolingConfigurationTests.cs @@ -0,0 +1,100 @@ +using FluentAssertions; + +namespace SatelliteProvider.Tests; + +public class ToolingConfigurationTests +{ + [Fact] + public void EditorConfig_ExistsAtRoot_AZ372_AC1() + { + var path = LocateRepoFile(".editorconfig"); + + path.Should().NotBeNull(".editorconfig must exist at the workspace root for `dotnet format` to honor formatting rules"); + + var content = File.ReadAllText(path!); + content.Should().Contain("root = true"); + content.Should().Contain("indent_style = space"); + content.Should().Contain("end_of_line = lf"); + content.Should().Contain("insert_final_newline = true"); + content.Should().Contain("trim_trailing_whitespace = true"); + } + + [Fact] + public void EditorConfig_DefinesInitialAnalyzerRuleset_AZ372_AC3() + { + var path = LocateRepoFile(".editorconfig"); + path.Should().NotBeNull(); + + var content = File.ReadAllText(path!); + + content.Should().Contain("dotnet_diagnostic.CA1001.severity = warning"); + content.Should().Contain("dotnet_diagnostic.CA1051.severity = warning"); + content.Should().Contain("dotnet_diagnostic.CA1816.severity = warning"); + content.Should().Contain("dotnet_diagnostic.CA2227.severity = warning"); + } + + [Fact] + public void DirectoryBuildProps_ExistsAtRoot_AZ372_AC3() + { + var path = LocateRepoFile("Directory.Build.props"); + path.Should().NotBeNull("Directory.Build.props centralizes analyzer settings for every csproj"); + + var content = File.ReadAllText(path!); + + content.Should().Contain("true"); + content.Should().Contain("latest"); + content.Should().Contain("None", + "AnalysisMode=None ensures only rules explicitly enabled in .editorconfig fire; protects against analyzer flood"); + } + + [Fact] + public void RunTestsScript_WiresFormatVerify_AZ372_AC1() + { + var path = LocateRepoFile(Path.Combine("scripts", "run-tests.sh")); + path.Should().NotBeNull(); + + var content = File.ReadAllText(path!); + + content.Should().Contain("dotnet format whitespace"); + content.Should().Contain("--verify-no-changes", + "AC-1 requires the script to gate on whitespace conformance via dotnet format"); + } + + [Fact] + public void RunTestsScript_CollectsCoverage_AZ372_AC2() + { + var path = LocateRepoFile(Path.Combine("scripts", "run-tests.sh")); + path.Should().NotBeNull(); + + var content = File.ReadAllText(path!); + + content.Should().Contain("XPlat Code Coverage"); + } + + [Fact] + public void TestProject_ReferencesCoverletCollector_AZ372_AC2() + { + var path = LocateRepoFile(Path.Combine("SatelliteProvider.Tests", "SatelliteProvider.Tests.csproj")); + path.Should().NotBeNull(); + + var content = File.ReadAllText(path!); + + content.Should().Contain("coverlet.collector", + "Coverlet collector is the data collector that produces XPlat Code Coverage reports"); + } + + private static string? LocateRepoFile(string relativePath) + { + var dir = new DirectoryInfo(Directory.GetCurrentDirectory()); + while (dir is not null) + { + var candidate = Path.Combine(dir.FullName, relativePath); + if (File.Exists(candidate)) + { + return candidate; + } + dir = dir.Parent; + } + return null; + } +} diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 4a9cade..61628b8 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -11,40 +11,62 @@ trap cleanup EXIT usage() { cat <