diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 662120b..a91ea19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,4 +36,4 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test --no-restore \ No newline at end of file + run: dotnet test --no-restore --filter Category!=Samples \ No newline at end of file diff --git a/NMatcher.sln b/NMatcher.sln index 8459dc3..06eb026 100644 --- a/NMatcher.sln +++ b/NMatcher.sln @@ -17,6 +17,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMatcher.FluentAssertions", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMatcher.FluentAssertions.Tests", "tests\NMatcher.FluentAssertions.Tests\NMatcher.FluentAssertions.Tests.csproj", "{0DF37F7A-4722-4873-B00F-C8A280F8FADA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{3964488E-ED62-4F41-970C-763841630355}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMatcher.Samples.Api", "samples\NMatcher.Samples.Api\NMatcher.Samples.Api.csproj", "{E6718A10-90BF-4A12-9F62-A41EA160029B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMatcher.Samples.Api.Tests", "samples\NMatcher.Samples.Api.Tests\NMatcher.Samples.Api.Tests.csproj", "{B23EE86F-B5EB-43DA-BCDA-133579782271}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,6 +49,12 @@ Global {0DF37F7A-4722-4873-B00F-C8A280F8FADA}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DF37F7A-4722-4873-B00F-C8A280F8FADA}.Release|Any CPU.ActiveCfg = Release|Any CPU {0DF37F7A-4722-4873-B00F-C8A280F8FADA}.Release|Any CPU.Build.0 = Release|Any CPU + {E6718A10-90BF-4A12-9F62-A41EA160029B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6718A10-90BF-4A12-9F62-A41EA160029B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6718A10-90BF-4A12-9F62-A41EA160029B}.Release|Any CPU.Build.0 = Release|Any CPU + {B23EE86F-B5EB-43DA-BCDA-133579782271}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B23EE86F-B5EB-43DA-BCDA-133579782271}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B23EE86F-B5EB-43DA-BCDA-133579782271}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -53,6 +65,8 @@ Global {4DE59B9C-826D-441C-878F-C7A4E65DC35B} = {7E005CFE-FF3B-4E55-B8C4-96E8F2AB4481} {CB8E085C-5062-4AD3-A954-BF64C6B0766B} = {5EA69303-20C6-4906-8F93-298D65E73A92} {0DF37F7A-4722-4873-B00F-C8A280F8FADA} = {7E005CFE-FF3B-4E55-B8C4-96E8F2AB4481} + {E6718A10-90BF-4A12-9F62-A41EA160029B} = {3964488E-ED62-4F41-970C-763841630355} + {B23EE86F-B5EB-43DA-BCDA-133579782271} = {3964488E-ED62-4F41-970C-763841630355} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DAE6A9BE-43BC-4653-BC7C-191832BB7F84} diff --git a/samples/NMatcher.Samples.Api.Tests/Integration/WeatherForecastControllerTests.cs b/samples/NMatcher.Samples.Api.Tests/Integration/WeatherForecastControllerTests.cs new file mode 100644 index 0000000..84cbb95 --- /dev/null +++ b/samples/NMatcher.Samples.Api.Tests/Integration/WeatherForecastControllerTests.cs @@ -0,0 +1,31 @@ +using FluentAssertions; +using NMatcher.FluentAssertions; + +namespace NMatcher.Samples.Api.Tests.Integration; + + +[Trait("Category", "Sample")] +public class WeatherForecastControllerTests +{ + [Fact] + public async Task test_weather_forecast_endpoint() + { + var program = new TestApiProgram(); + var client = program.CreateClient(); + + var rs = await client.GetAsync("/WeatherForecast"); + var response = await rs.Content.ReadAsStringAsync(); + + response.Should().MatchJson(@" + [ + { + ""date"": ""@string@.IsDateTime()"", + ""temperatureC"": ""@int@"", + ""temperatureF"": ""@int@"", + ""summary"": ""@string@.OneOf('Freezing', 'Cool', 'Mild', 'Warm', 'Balmy', 'Hot')"" + }, + ""@skip@"" + ] + "); + } +} \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api.Tests/NMatcher.Samples.Api.Tests.csproj b/samples/NMatcher.Samples.Api.Tests/NMatcher.Samples.Api.Tests.csproj new file mode 100644 index 0000000..0b88859 --- /dev/null +++ b/samples/NMatcher.Samples.Api.Tests/NMatcher.Samples.Api.Tests.csproj @@ -0,0 +1,31 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/samples/NMatcher.Samples.Api.Tests/TestApiProgram.cs b/samples/NMatcher.Samples.Api.Tests/TestApiProgram.cs new file mode 100644 index 0000000..0a7cbc9 --- /dev/null +++ b/samples/NMatcher.Samples.Api.Tests/TestApiProgram.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc.Testing; + +namespace NMatcher.Samples.Api.Tests; + +sealed class TestApiProgram : WebApplicationFactory +{ + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder.UseEnvironment("Test"); + } +} \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api.Tests/Usings.cs b/samples/NMatcher.Samples.Api.Tests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/samples/NMatcher.Samples.Api.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api/Controllers/WeatherForecastController.cs b/samples/NMatcher.Samples.Api/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..08910cf --- /dev/null +++ b/samples/NMatcher.Samples.Api/Controllers/WeatherForecastController.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc; + +namespace NMatcher.Samples.Api.Controllers; + +[ApiController] +[Route("[controller]")] +public class WeatherForecastController : ControllerBase +{ + private static readonly string[] Summaries = new[] + { + "Freezing", "Cool", "Mild", "Warm", "Balmy", "Hot", + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateTime.Now.AddDays(index), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } +} \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api/NMatcher.Samples.Api.csproj b/samples/NMatcher.Samples.Api/NMatcher.Samples.Api.csproj new file mode 100644 index 0000000..195c847 --- /dev/null +++ b/samples/NMatcher.Samples.Api/NMatcher.Samples.Api.csproj @@ -0,0 +1,18 @@ + + + + net6.0; + enable + enable + 11 + + + + + + + + + + + diff --git a/samples/NMatcher.Samples.Api/Program.cs b/samples/NMatcher.Samples.Api/Program.cs new file mode 100644 index 0000000..8264bac --- /dev/null +++ b/samples/NMatcher.Samples.Api/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api/Properties/launchSettings.json b/samples/NMatcher.Samples.Api/Properties/launchSettings.json new file mode 100644 index 0000000..fc61a66 --- /dev/null +++ b/samples/NMatcher.Samples.Api/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:45067", + "sslPort": 44351 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5270", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7048;http://localhost:5270", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/samples/NMatcher.Samples.Api/WeatherForecast.cs b/samples/NMatcher.Samples.Api/WeatherForecast.cs new file mode 100644 index 0000000..7541fec --- /dev/null +++ b/samples/NMatcher.Samples.Api/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace NMatcher.Samples.Api; + +public class WeatherForecast +{ + public DateTime Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } +} \ No newline at end of file diff --git a/samples/NMatcher.Samples.Api/appsettings.Development.json b/samples/NMatcher.Samples.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/samples/NMatcher.Samples.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/samples/NMatcher.Samples.Api/appsettings.json b/samples/NMatcher.Samples.Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/samples/NMatcher.Samples.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}