diff --git a/.github/workflows/github-actions-ci.yaml b/.github/workflows/github-actions-ci.yaml
new file mode 100644
index 0000000..dbb42e6
--- /dev/null
+++ b/.github/workflows/github-actions-ci.yaml
@@ -0,0 +1,24 @@
+name: Continuous Integration
+
+on:
+ pull_request:
+ branches: [ "main" ]
+ push:
+ branches: [ "releases/**" ]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup .NET 8.x
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: '8.x'
+
+ - name: Build
+ run: dotnet build --property:Configuration=Debug "PosInformatique.FluentAssertions.Json.sln"
+
+ - name: Test with the dotnet CLI
+ run: dotnet test --property:Configuration=Debug "PosInformatique.FluentAssertions.Json.sln"
diff --git a/.github/workflows/github-actions-release.yml b/.github/workflows/github-actions-release.yml
new file mode 100644
index 0000000..aaacc5d
--- /dev/null
+++ b/.github/workflows/github-actions-release.yml
@@ -0,0 +1,36 @@
+name: Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ VersionPrefix:
+ type: string
+ description: The version of the library
+ required: true
+ default: 1.3.0
+ VersionSuffix:
+ type: string
+ description: The version suffix of the library (for example rc.1)
+
+run-name: ${{ inputs.VersionPrefix }}-${{ inputs.VersionSuffix }}
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup .NET 8.x
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: '8.x'
+
+ - name: Build
+ run: dotnet pack
+ --property:Configuration=Release
+ --property:VersionPrefix=${{ github.event.inputs.VersionPrefix }}
+ --property:VersionSuffix=${{ github.event.inputs.VersionSuffix }}
+ "src/FluentAssertions.Json/FluentAssertions.Json.csproj"
+
+ - name: Publish the package to nuget.org
+ run: dotnet nuget push "src/FluentAssertions.Json/bin/Release/*.nupkg" --api-key "${{ secrets.NUGET_APIKEY }}" --source https://api.nuget.org/v3/index.json
diff --git a/Directory.Build.props b/Directory.Build.props
index d39119a..796c9aa 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -31,10 +31,6 @@
stylecop.json
-
-
-
-
diff --git a/PosInformatique.FluentAssertions.Json.sln b/PosInformatique.FluentAssertions.Json.sln
index 106286f..6c91e91 100644
--- a/PosInformatique.FluentAssertions.Json.sln
+++ b/PosInformatique.FluentAssertions.Json.sln
@@ -22,12 +22,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7928175B
tests\.editorconfig = tests\.editorconfig
EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{E7CF7FC5-E257-4A28-8641-F41032340CA9}"
- ProjectSection(SolutionItems) = preProject
- build\azure-pipelines-ci.yaml = build\azure-pipelines-ci.yaml
- build\azure-pipelines-release.yaml = build\azure-pipelines-release.yaml
- EndProjectSection
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -48,7 +42,6 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7928175B-C3B3-4F81-B956-BF4E4F816436} = {882949E5-7DCE-4EB6-8E9A-CB88FD0ED1F9}
- {E7CF7FC5-E257-4A28-8641-F41032340CA9} = {882949E5-7DCE-4EB6-8E9A-CB88FD0ED1F9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0582B8EB-4FA4-488E-9953-9B7CEEE4E94F}
diff --git a/build/azure-pipelines-ci.yaml b/build/azure-pipelines-ci.yaml
deleted file mode 100644
index fced5ca..0000000
--- a/build/azure-pipelines-ci.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-trigger: none
-
-pool:
- vmImage: ubuntu-latest
-
-jobs:
-- job: Build
- displayName: Build the library
- steps:
- - task: DotNetCoreCLI@2
- name: BuildLibrary
- displayName: Build the library
- inputs:
- command: 'build'
- projects: 'PosInformatique.FluentAssertions.Json.sln'
- arguments: '--property:Configuration=Debug'
-
- - task: DotNetCoreCLI@2
- name: ExecuteUnitTests
- displayName: Execute the unit tests
- inputs:
- command: 'test'
- projects: 'PosInformatique.FluentAssertions.Json.sln'
- arguments: '--property:Configuration=Debug'
\ No newline at end of file
diff --git a/build/azure-pipelines-release.yaml b/build/azure-pipelines-release.yaml
deleted file mode 100644
index 7ac4e4d..0000000
--- a/build/azure-pipelines-release.yaml
+++ /dev/null
@@ -1,54 +0,0 @@
-parameters:
-- name: VersionPrefix
- displayName: The version of the library
- type: string
- default: 1.2.0
-- name: VersionSuffix
- displayName: The version suffix of the library (rc.1). Use a space ' ' if no suffix.
- type: string
- default: rc.1
-
-trigger: none
-pr: none
-
-pool:
- vmImage: ubuntu-latest
-
-jobs:
-- job: Build
- displayName: Build the library
- steps:
- - task: PowerShell@2
- name: UpdateBuildNumber
- displayName: Update build number
- inputs:
- targetType: 'inline'
- script: '
- if ("${{parameters.VersionSuffix}}".Trim() -eq "")
- {
- Write-Host "##vso[build.updatebuildnumber]${{parameters.VersionPrefix}}"
- }
- else
- {
- Write-Host "##vso[build.updatebuildnumber]${{parameters.VersionPrefix}}-${{parameters.VersionSuffix}}"
- }'
-
- - task: DotNetCoreCLI@2
- name: BuildLibrary
- displayName: Build the library
- inputs:
- command: 'pack'
- packagesToPack: 'src/FluentAssertions.Json/FluentAssertions.Json.csproj'
- configuration: 'Release'
- versioningScheme: 'off'
- buildProperties: 'VersionPrefix=${{parameters.VersionPrefix}};VersionSuffix=${{parameters.VersionSuffix}}'
- verbosityPack: 'Normal'
-
- - task: NuGetCommand@2
- name: PublishNuGetPackages
- displayName: Publish to NuGet
- inputs:
- command: 'push'
- packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg'
- nuGetFeedType: 'external'
- publishFeedCredentials: 'nuget.org'
\ No newline at end of file
diff --git a/src/FluentAssertions.Json/FluentAssertions.Json.csproj b/src/FluentAssertions.Json/FluentAssertions.Json.csproj
index 015d71b..bf34078 100644
--- a/src/FluentAssertions.Json/FluentAssertions.Json.csproj
+++ b/src/FluentAssertions.Json/FluentAssertions.Json.csproj
@@ -11,8 +11,12 @@
https://github.com/PosInformatique/PosInformatique.FluentAssertions.Json
README.md
+ 1.3.0
+ - Add new overload BeJsonDeserializableInto() method to test the string collections.
+ - Add new overload BeJsonDeserializableInto() method to test the string and numeric values.
+
1.2.0
- - Add new override BeJsonSerializableInto() method to test polymorphism serialization with discriminator JSON property.
+ - Add new overload BeJsonSerializableInto() method to test polymorphism serialization with discriminator JSON property.
- Add the support to assert the deserialization of root JSON array.
1.1.0
diff --git a/src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs b/src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs
index cde0951..08a7b80 100644
--- a/src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs
+++ b/src/FluentAssertions.Json/JsonFluentAssertionsExtensions.cs
@@ -12,6 +12,7 @@ namespace FluentAssertions
using FluentAssertions.Collections;
using FluentAssertions.Common;
using FluentAssertions.Equivalency;
+ using FluentAssertions.Numeric;
using FluentAssertions.Primitives;
using PosInformatique.FluentAssertions.Json;
@@ -105,7 +106,7 @@ public static void BeJsonDeserializableInto(this ObjectAssertions assertions,
///
/// Type of the element of the collection to check the JSON deserialization.
/// Type of the object to deserialize from JSON.
- /// which contains the JSON collection subject to deserialize.
+ /// which contains the JSON collection subject to deserialize.
/// Expected collection deserialized expected.
/// to use to assert the deserialization. If not specified
/// the default of the
@@ -115,6 +116,49 @@ public static void BeJsonDeserializableInto(this GenericCollectionA
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
}
+ ///
+ /// Check if the JSON subject string collection is deserializable into the specified argument.
+ ///
+ /// Type of the object to deserialize from JSON.
+ /// which contains the JSON string collection subject to deserialize.
+ /// Expected string collection deserialized expected.
+ /// to use to assert the deserialization. If not specified
+ /// the default of the
+ /// will be used.
+ public static void BeJsonDeserializableInto(this StringCollectionAssertions assertions, T expectedObject, JsonSerializerOptions? options = null)
+ {
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
+ }
+
+ ///
+ /// Check if the JSON subject numeric is deserializable into the specified argument.
+ ///
+ /// Type of the object to deserialize from JSON.
+ /// which contains the JSON numeric subject to deserialize.
+ /// Expected numeric value deserialized expected.
+ /// to use to assert the deserialization. If not specified
+ /// the default of the
+ /// will be used.
+ public static void BeJsonDeserializableInto(this NumericAssertions assertions, T expectedObject, JsonSerializerOptions? options = null)
+ where T : struct, IComparable
+ {
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
+ }
+
+ ///
+ /// Check if the JSON subject string is deserializable into the specified argument.
+ ///
+ /// Type of the object to deserialize from JSON.
+ /// which contains the JSON string subject to deserialize.
+ /// Expected string value deserialized expected.
+ /// to use to assert the deserialization. If not specified
+ /// the default of the
+ /// will be used.
+ public static void BeJsonDeserializableInto(this StringAssertions assertions, T expectedObject, JsonSerializerOptions? options = null)
+ {
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, GetSerializerOptions(options));
+ }
+
///
/// Check if the JSON subject object is deserializable into the specified argument.
///
@@ -150,6 +194,58 @@ public static void BeJsonDeserializableInto(this GenericCollectionA
BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
}
+ ///
+ /// Check if the JSON subject string collection is deserializable into the specified argument.
+ ///
+ /// Type of the object to deserialize from JSON.
+ /// which contains the JSON string collection subject to deserialize.
+ /// Expected string collection deserialized expected.
+ /// Allows to change the default
+ /// of the used to assert the deserialization.
+ public static void BeJsonDeserializableInto(this StringCollectionAssertions assertions, T expectedObject, Action configureOptions)
+ {
+ var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);
+
+ configureOptions(optionsCopy);
+
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
+ }
+
+ ///
+ /// Check if the JSON subject numeric is deserializable into the specified argument.
+ ///
+ /// Type of the numeric value to deserialize from JSON.
+ /// which contains the JSON numeric subject to deserialize.
+ /// Expected numeric value deserialized expected.
+ /// Allows to change the default
+ /// of the used to assert the deserialization.
+ public static void BeJsonDeserializableInto(this NumericAssertions assertions, T expectedObject, Action configureOptions)
+ where T : struct, IComparable
+ {
+ var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);
+
+ configureOptions(optionsCopy);
+
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
+ }
+
+ ///
+ /// Check if the JSON subject string is deserializable into the specified argument.
+ ///
+ /// Type of the string value to deserialize from JSON.
+ /// which contains the JSON string subject to deserialize.
+ /// Expected string value deserialized expected.
+ /// Allows to change the default
+ /// of the used to assert the deserialization.
+ public static void BeJsonDeserializableInto(this StringAssertions assertions, T expectedObject, Action configureOptions)
+ {
+ var optionsCopy = new JsonSerializerOptions(FluentAssertionsJson.Configuration.JsonSerializerOptions);
+
+ configureOptions(optionsCopy);
+
+ BeJsonDeserializableIntoCore(assertions.Subject, expectedObject, optionsCopy);
+ }
+
private static void BeJsonSerializableIntoCore(ObjectAssertions assertions, object? expectedJson, JsonSerializerOptions options)
{
if (assertions.Subject is not null && assertions.Subject is not TBase)
diff --git a/tests/FluentAssertions.Json.Tests/FluentAssertions.Json.Tests.csproj b/tests/FluentAssertions.Json.Tests/FluentAssertions.Json.Tests.csproj
index 96ab1ea..b48b3c2 100644
--- a/tests/FluentAssertions.Json.Tests/FluentAssertions.Json.Tests.csproj
+++ b/tests/FluentAssertions.Json.Tests/FluentAssertions.Json.Tests.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
disable
@@ -9,13 +9,13 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/tests/FluentAssertions.Json.Tests/JsonFluentAssertionsExtensionsTest.cs b/tests/FluentAssertions.Json.Tests/JsonFluentAssertionsExtensionsTest.cs
index 08c5870..b4258dd 100644
--- a/tests/FluentAssertions.Json.Tests/JsonFluentAssertionsExtensionsTest.cs
+++ b/tests/FluentAssertions.Json.Tests/JsonFluentAssertionsExtensionsTest.cs
@@ -1205,6 +1205,103 @@ public void BeJsonDeserializableInto_WithObjectProperty_String_WrongType()
.WithMessage("$.inner.object_property: Expected property to be 'Number' type instead of 'String' type.");
}
+ [Fact]
+ public void BeJsonDeserializableInto_WithArrayOfString()
+ {
+ var json = new[] { "A", "B", "C" };
+
+ json.Should().BeJsonDeserializableInto(new[] { "A", "B", "C" });
+ }
+
+ [Fact]
+ public void BeJsonDeserializableInto_WithArrayOfString_WithOptions()
+ {
+ var json = new[] { "A", "B", "C" };
+
+ json.Should().BeJsonDeserializableInto(
+ new[] { "A", "B", "C" },
+ new JsonSerializerOptions()
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ });
+ }
+
+ [Fact]
+ public void BeJsonDeserializableInto_ArrayOfString_WithOptionsConfigure()
+ {
+ var json = new[] { "A", "B", "C" };
+
+ json.Should().BeJsonDeserializableInto(
+ new[] { "A", "B", "C" },
+ opt =>
+ {
+ opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ });
+ }
+
+ [Fact]
+ public void BeJsonDeserializableInto_PrimitiveValues()
+ {
+ var json = "A";
+
+ json.Should().BeJsonDeserializableInto("A");
+
+ var json2 = 1234;
+
+ json2.Should().BeJsonDeserializableInto(1234);
+
+ var json3 = 12.34;
+
+ json3.Should().BeJsonDeserializableInto(12.34);
+ }
+
+ [Fact]
+ public void BeJsonDeserializableInto_PrimitiveValues_WithOptions()
+ {
+ var json = "A";
+
+ json.Should().BeJsonDeserializableInto("A", new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+ var json2 = 1234;
+
+ json2.Should().BeJsonDeserializableInto(1234, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+
+ var json3 = 12.34;
+
+ json3.Should().BeJsonDeserializableInto(12.34, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
+ }
+
+ [Fact]
+ public void BeJsonDeserializableInto_PrimitiveValues_WithOptionsConfigure()
+ {
+ var json = "A";
+
+ json.Should().BeJsonDeserializableInto(
+ "A",
+ opt =>
+ {
+ opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ });
+
+ var json2 = 1234;
+
+ json2.Should().BeJsonDeserializableInto(
+ 1234,
+ opt =>
+ {
+ opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ });
+
+ var json3 = 12.34;
+
+ json3.Should().BeJsonDeserializableInto(
+ 12.34,
+ opt =>
+ {
+ opt.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+ });
+ }
+
private class JsonSerializableClass
{
[JsonPropertyName("string_property")]