diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f3fe9d..98b9bbf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,10 +28,13 @@ jobs: sourceRepositoryCommit: $env:GITHUB_SHA steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET Core SDK - uses: actions/setup-dotnet@v1.7.2 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.101 + architecture: x64 - name: Dotnet restore run: dotnet restore --verbosity ${{ env.dotnetVerbosity }} @@ -64,7 +67,7 @@ jobs: shell: pwsh - name: Upload packages - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifactName }} path: | diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 65b5f61..1b88af1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -26,11 +26,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -41,7 +41,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v4 diff --git a/ActiveLogin.Identity.sln b/ActiveLogin.Identity.sln index 7db3733..e8ce419 100644 --- a/ActiveLogin.Identity.sln +++ b/ActiveLogin.Identity.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32112.339 +# Visual Studio Version 18 +VisualStudioVersion = 18.4.11519.219 insiders MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9A0CF459-87CC-448D-B49D-EFC3D6482AA6}" EndProject diff --git a/global.json b/global.json index 74f1493..37bf7f8 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.102", + "version": "10.0.101", "rollForward": "latestFeature" } } diff --git a/samples/ConsoleSample.CSharp/ConsoleSample.CSharp.csproj b/samples/ConsoleSample.CSharp/ConsoleSample.CSharp.csproj index 8c38376..81aa33f 100644 --- a/samples/ConsoleSample.CSharp/ConsoleSample.CSharp.csproj +++ b/samples/ConsoleSample.CSharp/ConsoleSample.CSharp.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net10.0 latest enable true diff --git a/samples/ConsoleSample.CSharp/Program.cs b/samples/ConsoleSample.CSharp/Program.cs index 1409090..e9ba0d0 100644 --- a/samples/ConsoleSample.CSharp/Program.cs +++ b/samples/ConsoleSample.CSharp/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using ActiveLogin.Identity.Swedish; @@ -168,7 +168,7 @@ private static void Sample_ParseUserInput() { WriteHeader("What is your (Swedish) Personal Identity Number or Coordination Number?"); var userRawPersonalIdentityNumber = Console.ReadLine(); - WriteIndividualIdentityNumberInfo(userRawPersonalIdentityNumber); + WriteIndividualIdentityNumberInfo(userRawPersonalIdentityNumber ?? ""); } #endregion diff --git a/samples/ConsoleSample.FSharp/ConsoleSample.FSharp.fsproj b/samples/ConsoleSample.FSharp/ConsoleSample.FSharp.fsproj index ab7d29e..0de149b 100644 --- a/samples/ConsoleSample.FSharp/ConsoleSample.FSharp.fsproj +++ b/samples/ConsoleSample.FSharp/ConsoleSample.FSharp.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net10.0 true diff --git a/src/ActiveLogin.Identity.Swedish.AspNetCore/ActiveLogin.Identity.Swedish.AspNetCore.csproj b/src/ActiveLogin.Identity.Swedish.AspNetCore/ActiveLogin.Identity.Swedish.AspNetCore.csproj index d7b6291..a753f3b 100644 --- a/src/ActiveLogin.Identity.Swedish.AspNetCore/ActiveLogin.Identity.Swedish.AspNetCore.csproj +++ b/src/ActiveLogin.Identity.Swedish.AspNetCore/ActiveLogin.Identity.Swedish.AspNetCore.csproj @@ -40,11 +40,11 @@ - + - + diff --git a/src/ActiveLogin.Identity.Swedish.TestData/ActiveLogin.Identity.Swedish.TestData.fsproj b/src/ActiveLogin.Identity.Swedish.TestData/ActiveLogin.Identity.Swedish.TestData.fsproj index 79d8a53..7cf4438 100644 --- a/src/ActiveLogin.Identity.Swedish.TestData/ActiveLogin.Identity.Swedish.TestData.fsproj +++ b/src/ActiveLogin.Identity.Swedish.TestData/ActiveLogin.Identity.Swedish.TestData.fsproj @@ -39,7 +39,7 @@ - + diff --git a/src/ActiveLogin.Identity.Swedish/ActiveLogin.Identity.Swedish.fsproj b/src/ActiveLogin.Identity.Swedish/ActiveLogin.Identity.Swedish.fsproj index 75adcc2..a2d09d8 100644 --- a/src/ActiveLogin.Identity.Swedish/ActiveLogin.Identity.Swedish.fsproj +++ b/src/ActiveLogin.Identity.Swedish/ActiveLogin.Identity.Swedish.fsproj @@ -39,7 +39,7 @@ - + diff --git a/src/ActiveLogin.Identity.Swedish/CoordinationNumber.fs b/src/ActiveLogin.Identity.Swedish/CoordinationNumber.fs index 528ef0f..77a7d2f 100644 --- a/src/ActiveLogin.Identity.Swedish/CoordinationNumber.fs +++ b/src/ActiveLogin.Identity.Swedish/CoordinationNumber.fs @@ -55,19 +55,13 @@ module internal CoordinationNumber = parseInSpecificYearInternal strictMode parseYear str let tryParseInSpecificYear strictMode parseYear str = - try - parseInSpecificYearInternal strictMode parseYear str - |> Some - with - exn -> None + let pYear = Year.create parseYear + Parse.tryParseInSpecificYear create strictMode pYear str let parse strictMode str = Parse.parse create strictMode str let tryParse strictMode str = - try - parse strictMode str |> Some - with - exn -> None + Parse.tryParse create strictMode str open CoordinationNumber diff --git a/src/ActiveLogin.Identity.Swedish/IndividualIdentityNumber.fs b/src/ActiveLogin.Identity.Swedish/IndividualIdentityNumber.fs index e6ffb1b..f735a8a 100644 --- a/src/ActiveLogin.Identity.Swedish/IndividualIdentityNumber.fs +++ b/src/ActiveLogin.Identity.Swedish/IndividualIdentityNumber.fs @@ -26,18 +26,13 @@ module internal IndividualIdentityNumber = parseInSpecificYearInternal parseYear str let tryParseInSpecificYear parseYear str = - try - parseInSpecificYearInternal parseYear str |> Some - with - exn -> None + let pYear = parseYear |> Year.create + Parse.tryParseInSpecificYear create StrictModeInternal.Off pYear str let parse str = Parse.parse create StrictModeInternal.Off str let tryParse str = - try - parse str |> Some - with - exn -> None + Parse.tryParse create StrictModeInternal.Off str let to10DigitStringInSpecificYear serializationYear (num: IndividualIdentityNumberInternal) = match num with diff --git a/src/ActiveLogin.Identity.Swedish/Parse.fs b/src/ActiveLogin.Identity.Swedish/Parse.fs index f61288b..f17857d 100644 --- a/src/ActiveLogin.Identity.Swedish/Parse.fs +++ b/src/ActiveLogin.Identity.Swedish/Parse.fs @@ -150,23 +150,40 @@ module private Helpers = let checksum = str.[10..10] |> int (fullYear, month, day, birthNumber, checksum) -let tee f x = f x; x -let parseInSpecificYear createFunc strictMode parseYear str = - try - str - |> Helpers.requireNotEmpty - |> Helpers.requireDigitCount strictMode - |> Helpers.clean strictMode - |> Helpers.addImplicitHyphen - |> Helpers.parseNumberValues parseYear - |> createFunc - with - | :? ArgumentOutOfRangeException as ex -> - FormatException(sprintf "String was not recognized as a valid IdentityNumber. %s" ex.Message, ex) |> raise - | :? ArgumentNullException -> reraise() - | :? ArgumentException as ex -> - FormatException(sprintf "String was not recognized as a valid IdentityNumber. %s" ex.Message, ex) |> raise - -let parse createFunc strictMode str = - let year = DateTime.UtcNow.Year |> Year.create - parseInSpecificYear createFunc strictMode year str +let tee f x = f x; x + +let private runPipeline createFunc strictMode parseYear str = + str + |> Helpers.requireNotEmpty + |> Helpers.requireDigitCount strictMode + |> Helpers.clean strictMode + |> Helpers.addImplicitHyphen + |> Helpers.parseNumberValues parseYear + |> createFunc + +let tryParseInSpecificYear createFunc strictMode parseYear str = + try + runPipeline createFunc strictMode parseYear str |> Some + with + | :? ArgumentNullException -> None + | :? ArgumentOutOfRangeException -> None + | :? ArgumentException -> None + | :? FormatException -> None + +let parseInSpecificYear createFunc strictMode parseYear str = + try + runPipeline createFunc strictMode parseYear str + with + | :? ArgumentOutOfRangeException as ex -> + FormatException(sprintf "String was not recognized as a valid IdentityNumber. %s" ex.Message, ex) |> raise + | :? ArgumentNullException -> reraise() + | :? ArgumentException as ex -> + FormatException(sprintf "String was not recognized as a valid IdentityNumber. %s" ex.Message, ex) |> raise + +let tryParse createFunc strictMode str = + let year = DateTime.UtcNow.Year |> Year.create + tryParseInSpecificYear createFunc strictMode year str + +let parse createFunc strictMode str = + let year = DateTime.UtcNow.Year |> Year.create + parseInSpecificYear createFunc strictMode year str diff --git a/src/ActiveLogin.Identity.Swedish/PersonalIdentityNumber.fs b/src/ActiveLogin.Identity.Swedish/PersonalIdentityNumber.fs index 5c6f97f..b9affab 100644 --- a/src/ActiveLogin.Identity.Swedish/PersonalIdentityNumber.fs +++ b/src/ActiveLogin.Identity.Swedish/PersonalIdentityNumber.fs @@ -53,20 +53,13 @@ module internal PersonalIdentityNumber = parseInSpecificYearInternal strictMode parseYear str let tryParseInSpecificYear strictMode parseYear str = - try - parseInSpecificYearInternal strictMode parseYear str - |> Some - with - exn -> None + let pYear = parseYear |> Year.create + Parse.tryParseInSpecificYear create strictMode pYear str let parse strictMode str = Parse.parse create strictMode str let tryParse strictMode str = - try - parse strictMode str - |> Some - with - exn -> None + Parse.tryParse create strictMode str open PersonalIdentityNumber diff --git a/test/ActiveLogin.Identity.Swedish.AspNetCore.Test/ActiveLogin.Identity.Swedish.AspNetCore.Test.csproj b/test/ActiveLogin.Identity.Swedish.AspNetCore.Test/ActiveLogin.Identity.Swedish.AspNetCore.Test.csproj index be62bbd..653f44c 100644 --- a/test/ActiveLogin.Identity.Swedish.AspNetCore.Test/ActiveLogin.Identity.Swedish.AspNetCore.Test.csproj +++ b/test/ActiveLogin.Identity.Swedish.AspNetCore.Test/ActiveLogin.Identity.Swedish.AspNetCore.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 true false @@ -9,13 +9,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers - + diff --git a/test/ActiveLogin.Identity.Swedish.Benchmarks/ActiveLogin.Identity.Swedish.Benchmarks.fsproj b/test/ActiveLogin.Identity.Swedish.Benchmarks/ActiveLogin.Identity.Swedish.Benchmarks.fsproj index 7425f15..cb4c430 100644 --- a/test/ActiveLogin.Identity.Swedish.Benchmarks/ActiveLogin.Identity.Swedish.Benchmarks.fsproj +++ b/test/ActiveLogin.Identity.Swedish.Benchmarks/ActiveLogin.Identity.Swedish.Benchmarks.fsproj @@ -2,13 +2,13 @@ Exe - net6.0 + net10.0 false true - + diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/ActiveLogin.Identity.Swedish.FSharp.Test.fsproj b/test/ActiveLogin.Identity.Swedish.FSharp.Test/ActiveLogin.Identity.Swedish.FSharp.Test.fsproj index 587b327..81b8cf3 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/ActiveLogin.Identity.Swedish.FSharp.Test.fsproj +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/ActiveLogin.Identity.Swedish.FSharp.Test.fsproj @@ -1,8 +1,8 @@ - + Exe - net6.0 + net10.0 false false true @@ -29,12 +29,12 @@ - - - - - - + + + + + + diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Constructor.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Constructor.fs index 9b4ddf1..e077b42 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Constructor.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Constructor.fs @@ -22,62 +22,56 @@ let tests = |> CoordinationNumber pin.To12DigitString() =! str - testPropWithMaxTest 20000 "with invalid year throws" <| - fun (Gen.CoordNum.ValidValues (_, m, d, b, c), Gen.InvalidYear invalidYear) -> - toAction CoordinationNumber (invalidYear, m, d, b, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid year" + testPropWithMaxTest 20000 "with invalid year throws" <| fun (Gen.CoordNum.ValidValues (_, m, d, b, c), Gen.InvalidYear invalidYear) -> + let action = fun () -> CoordinationNumber (invalidYear, m, d, b, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid year" action testPropWithMaxTest 20000 "with valid year does not throw exception for year" <| fun (Gen.CoordNum.ValidValues (_, m, d, b, c), Gen.ValidYear validYear) -> toAction CoordinationNumber (validYear, m, d, b, c) |> Expect.doesNotThrowWithMessage "Invalid year" - testProp "with invalid month throws exception" <| - fun (Gen.CoordNum.WithInvalidMonth withInvalidMonth) -> - toAction CoordinationNumber withInvalidMonth - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid month for coordination number" + testProp "with invalid month throws exception" <| fun (Gen.CoordNum.WithInvalidMonth withInvalidMonth) -> + let action = fun () -> CoordinationNumber withInvalidMonth |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid month for coordination number" action testProp "valid month does not throw exception for month" <| fun (Gen.CoordNum.ValidValues (y, _, d, b, c), Gen.ValidMonth validMonth) -> toAction CoordinationNumber (y, validMonth, d, b, c) |> Expect.doesNotThrowWithMessage "Invalid month for coordination number" - testProp "with invalid day throws" <| - fun (Gen.CoordNum.WithInvalidDay withInvalidDay) -> - toAction CoordinationNumber withInvalidDay - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid coordination day" + testProp "with invalid day throws" <| fun (Gen.CoordNum.WithInvalidDay withInvalidDay) -> + let action = fun () -> CoordinationNumber withInvalidDay |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid coordination day" action testProp "with valid day does not throw exception for day" <| fun (Gen.CoordNum.WithValidDay withValidDay) -> toAction CoordinationNumber withValidDay |> Expect.doesNotThrowWithMessage "Invalid coordination day" - testProp "with invalid individual number throws" <| - fun (Gen.CoordNum.ValidValues (y, m, d, _, c), Gen.InvalidBirthNumber invalidBirthNumber) -> - toAction CoordinationNumber (y, m, d, invalidBirthNumber, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid individual number" + testProp "with invalid individual number throws" <| fun (Gen.CoordNum.ValidValues (y, m, d, _, c), Gen.InvalidBirthNumber invalidBirthNumber) -> + let action = fun () -> CoordinationNumber (y, m, d, invalidBirthNumber, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid individual number" action testPropWithMaxTest 3000 "with valid individual number does not throw exception for birth number" <| fun (Gen.CoordNum.ValidValues (y, m, d, _, c), Gen.ValidBirthNumber validBirthNumber) -> toAction CoordinationNumber (y, m, d, validBirthNumber, c ) |> Expect.doesNotThrowWithMessage "Invalid individual number" - testProp "with invalid checksum throws" <| - fun (Gen.CoordNum.ValidValues (y, m, d, b, c)) -> - let invalidChecksums = - [ 0..9 ] - |> List.except [ c ] - - let withInvalidChecksums = - invalidChecksums - |> List.map (fun checksum -> (y, m, d, b, checksum)) - - withInvalidChecksums - |> List.iter (fun (y, m, d, b, cs) -> - toAction CoordinationNumber (y, m, d, b, cs) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid checksum" ) + testProp "with invalid checksum throws" <| fun (Gen.CoordNum.ValidValues (y, m, d, b, c)) -> + let invalidChecksums = + [0..9] |> List.except [c] + + let withInvalidChecksums = + invalidChecksums |> List.map (fun cs -> (y, m, d, b, cs)) + + withInvalidChecksums + |> List.iter (fun (y, m, d, b, cs) -> + let action = fun () -> CoordinationNumber (y, m, d, b, cs) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid checksum" action + ) ] diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Parse.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Parse.fs index d409c84..e4ec9f8 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Parse.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_Parse.fs @@ -76,16 +76,16 @@ let tests = |> Expect.throwsWithType |> ignore } testProp "empty string returns parsing error" <| fun (Gen.EmptyString str) -> - toAction parse str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parse str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parse digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." ) + let action = fun () -> parse digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action testProp "num with invalid year returns parsing error" <| fun (Gen.CoordNum.NumWithInvalidYear str) -> toAction parse str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -102,9 +102,9 @@ let tests = toAction parse str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string returns parsing error" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseInSpecificYear (null, year) |> Expect.throwsWithType diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_ParseStrict.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_ParseStrict.fs index 22e0cf8..f01c309 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_ParseStrict.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/CoordinationNumber_ParseStrict.fs @@ -47,51 +47,47 @@ let tests = testList "invalid coordination number - StrictMode.TenDigits" [ testProp "12 digit string" <| fun (Gen.CoordNum.ValidNum pin) -> - toAction parseStrictTenDigits (pin.To12DigitString()) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." + let action = fun () -> parseStrictTenDigits (pin.To12DigitString()) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action - testProp "string mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." - testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> removeHyphen - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." + testProp "string mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action + + testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> removeHyphen |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action test "null string throws" { toAction parseStrictTenDigits null |> Expect.throwsWithType |> ignore } testProp "empty string throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTenDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." ) + let action = fun () -> parseStrictTenDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action testProp "pin with invalid month returns parsing error" <| fun (Gen.CoordNum.NumWithInvalidMonth str) -> toAction parseStrictTenDigits str.[2..] |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; " Invalid month"] @@ -105,9 +101,9 @@ let tests = toAction parseStrictTenDigits str.[2..] |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTenDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTenDigitsInSpecificYear (null, year) |> Expect.throwsWithType @@ -129,59 +125,55 @@ let tests = testList "invalid coordination number - StrictMode.TwelveDigits" [ testProp "10 digit string without hyphen-delimiter" <| fun (Gen.CoordNum.ValidNum pin) -> - pin.To10DigitString() - |> removeHyphen - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - - testProp "10 digit string mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - + let str = pin.To10DigitString() |> removeHyphen + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + + testProp "10 digit string mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + testProp "10 digit string with delimiter" <| fun (Gen.CoordNum.ValidNum pin) -> - pin.To10DigitString() - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - + let str = pin.To10DigitString() + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + testPropWithMaxTest 400 "10 digit string 'in specific year'" <| fun (Gen.CoordNum.ValidNum pin) -> let offset = rng.Next (0, 200) let year = pin.Year + offset - (pin.To10DigitStringInSpecificYear year, year) - |> toAction parseStrictTwelveDigitsInSpecificYear - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - - testProp "12 digit string mixed with 'non-digits'" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutDigits = - charArray - |> Array.filter (isDigit >> not) - pin.To12DigitString() - |> surroundEachChar charsWithoutDigits - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - - testPropWithMaxTest 400 "10 digit string without hyphen delimiter 'in specific year'" - <| fun (Gen.CoordNum.ValidNum pin) -> - let offset = rng.Next (0, 200) - let year = pin.Year + offset - let str = - pin.To10DigitStringInSpecificYear year - |> removeHyphen - toAction parseStrictTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." + let str = pin.To10DigitStringInSpecificYear year + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + + testProp "12 digit string mixed with 'non-digits'" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutDigits = charArray |> Array.filter (isDigit >> not) + let str = pin.To12DigitString() |> surroundEachChar charsWithoutDigits + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + + testPropWithMaxTest 400 "10 digit string without hyphen delimiter 'in specific year'" <| fun (Gen.CoordNum.ValidNum pin) -> + let offset = rng.Next (0, 200) + let year = pin.Year + offset + let str = pin.To10DigitStringInSpecificYear year |> removeHyphen + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action test "null string throws" { toAction parseStrictTwelveDigits null @@ -189,16 +181,16 @@ let tests = |> ignore } testProp "empty string throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTwelveDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTwelveDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." ) + let action = fun () -> parseStrictTwelveDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action testProp "pin with invalid year returns parsing error" <| fun (Gen.CoordNum.NumWithInvalidYear str) -> toAction parseStrictTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -215,9 +207,9 @@ let tests = toAction parseStrictTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTwelveDigitsInSpecificYear (null, year) |> Expect.throwsWithType @@ -259,47 +251,42 @@ let tests = testList "invalid coordination number - StrictMode.TenOrTwelveDigits" [ - testProp "string mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." - testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> removeHyphen - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." + testProp "string mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action + + testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> removeHyphen |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action test "null string throws" { toAction parseStrictTenOrTwelveDigits null |> Expect.throwsWithType |> ignore } testProp "empty string returns throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTenOrTwelveDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." ) + let action = fun () -> parseStrictTenOrTwelveDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action testProp "pin with invalid year returns parsing error" <| fun (Gen.CoordNum.NumWithInvalidYear str) -> toAction parseStrictTenOrTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -316,35 +303,31 @@ let tests = toAction parseStrictTenOrTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTenOrTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenOrTwelveDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTenOrTwelveDigitsInSpecificYear (null, year) |> Expect.throwsWithType |> ignore - testProp "10 digit string mixed with 'non-digits' except plus" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - |> toAction parseStrictTenOrTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." - - testProp "12 digit string mixed with 'non-digits'" - <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> - let charsWithoutDigits = - charArray - |> Array.filter (isDigit >> not) - pin.To12DigitString() - |> surroundEachChar charsWithoutDigits - |> toAction parseStrictTenOrTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." + testProp "10 digit string mixed with 'non-digits' except plus" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action + + testProp "12 digit string mixed with 'non-digits'" <| fun (Gen.CoordNum.ValidNum pin, Gen.Char100 charArray) -> + let charsWithoutDigits = charArray |> Array.filter (isDigit >> not) + let str = pin.To12DigitString() |> surroundEachChar charsWithoutDigits + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action ] ] diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Constructor.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Constructor.fs index 207e985..af638b0 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Constructor.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Constructor.fs @@ -22,62 +22,56 @@ let tests = |> Gen.stringToValues |> PersonalIdentityNumber pin.To12DigitString() =! str - testPropWithMaxTest 20000 "with invalid year throws" <| - fun (Gen.Pin.ValidValues (_, m, d, b, c), Gen.InvalidYear invalidYear) -> - toAction PersonalIdentityNumber (invalidYear, m, d, b, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid year" + testPropWithMaxTest 20000 "with invalid year throws" <| fun (Gen.Pin.ValidValues (_, m, d, b, c), Gen.InvalidYear invalidYear) -> + let action = fun () -> PersonalIdentityNumber (invalidYear, m, d, b, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid year" action testPropWithMaxTest 20000 "with valid year does not throw exception for year" <| fun (Gen.Pin.ValidValues (_, m, d, b, c), Gen.ValidYear validYear) -> toAction PersonalIdentityNumber (validYear, m, d, b, c) |> Expect.doesNotThrowWithMessage "Invalid year" - testProp "with invalid month throws" <| - fun (Gen.Pin.ValidValues (y, _, d, b, c), Gen.InvalidMonth invalidMonth) -> - toAction PersonalIdentityNumber (y, invalidMonth, d, b, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid month" + testProp "with invalid month throws" <| fun (Gen.Pin.ValidValues (y, _, d, b, c), Gen.InvalidMonth invalidMonth) -> + let action = fun () -> PersonalIdentityNumber (y, invalidMonth, d, b, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid month" action testProp "with valid month does not throw exception for month" <| fun (Gen.Pin.ValidValues (y, _, d, b, c), Gen.ValidMonth validMonth) -> toAction PersonalIdentityNumber (y, validMonth, d, b, c) |> Expect.doesNotThrowWithMessage "Invalid month" - testProp "with invalid day throws" <| - fun (Gen.Pin.WithInvalidDay (y, m, d, b, c)) -> - toAction PersonalIdentityNumber (y, m, d, b, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid day of month" + testProp "with invalid day throws" <| fun (Gen.Pin.WithInvalidDay (y, m, d, b, c)) -> + let action = fun () -> PersonalIdentityNumber (y, m, d, b, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid day of month" action testProp "with valid day does not throw exception for day" <| fun (Gen.Pin.WithValidDay (y, m, d, b, c)) -> toAction PersonalIdentityNumber (y, m, d, b, c) |> Expect.doesNotThrowWithMessage "Invalid day of month" - testProp "with invalid birth number throws" <| - fun (Gen.Pin.ValidValues (y, m, d, _, c), Gen.InvalidBirthNumber invalidBirthNumber) -> - toAction PersonalIdentityNumber (y, m, d, invalidBirthNumber, c) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid birth number" + testProp "with invalid birth number throws" <| fun (Gen.Pin.ValidValues (y, m, d, _, c), Gen.InvalidBirthNumber invalidBirthNumber) -> + let action = fun () -> PersonalIdentityNumber (y, m, d, invalidBirthNumber, c) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid birth number" action testPropWithMaxTest 3000 "with valid birth number does not throw exception for birth number" <| fun (Gen.Pin.ValidValues (y, m, d, _, c), Gen.ValidBirthNumber validBirthNumber) -> toAction PersonalIdentityNumber (y, m, d, validBirthNumber, c) |> Expect.doesNotThrowWithMessage "Invalid birth number" - testProp "invalid checksum throws" <| - fun (Gen.Pin.ValidValues (y, m, d, b, c)) -> - let invalidChecksums = - [ 0..9 ] - |> List.except [ c ] - - let withInvalidChecksums = - invalidChecksums - |> List.map (fun checksum -> (y, m, d, b, checksum)) - - withInvalidChecksums - |> List.iter (fun (y, m, d, b, cs) -> - toAction PersonalIdentityNumber (y, m, d, b, cs) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "Invalid checksum" ) + testProp "invalid checksum throws" <| fun (Gen.Pin.ValidValues (y, m, d, b, c)) -> + let invalidChecksums = + [0..9] |> List.except [c] + + let withInvalidChecksums = + invalidChecksums |> List.map (fun cs -> (y, m, d, b, cs)) + + withInvalidChecksums + |> List.iter (fun (y, m, d, b, cs) -> + let action = fun () -> PersonalIdentityNumber (y, m, d, b, cs) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "Invalid checksum" action + ) ] diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Parse.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Parse.fs index 2a1c957..f231ac6 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Parse.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_Parse.fs @@ -76,16 +76,16 @@ let tests = |> ignore } testProp "empty string returns throws" <| fun (Gen.EmptyString str) -> - toAction parse str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parse str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parse digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." ) + let action = fun () -> parse digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action testProp "pin with invalid year returns parsing error" <| fun (Gen.Pin.PinWithInvalidYear str) -> toAction parse str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -102,9 +102,9 @@ let tests = toAction parse str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseInSpecificYear (null, year) |> Expect.throwsWithType diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_ParseStrict.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_ParseStrict.fs index 3000687..08627cb 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_ParseStrict.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PersonalIdentityNumber_ParseStrict.fs @@ -44,51 +44,57 @@ let tests = testList "invalid personal identity number - StrictMode.TenDigits" [ testProp "12 digit string" <| fun (Gen.Pin.ValidPin pin) -> - toAction parseStrictTenDigits (pin.To12DigitString()) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." + let action = fun () -> parseStrictTenDigits (pin.To12DigitString()) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action testProp "string mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." + <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = + pin.To10DigitString() + |> surroundEachChar charsWithoutPlus + + let action = fun () -> parseStrictTenDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action + testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> removeHyphen - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." + <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = + pin.To10DigitString() + |> removeHyphen + |> surroundEachChar charsWithoutPlus + + let action = fun () -> parseStrictTenDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action + test "null string throws" { toAction parseStrictTenDigits null |> Expect.throwsWithType |> ignore } testProp "empty string throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTenDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTenDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." ) + let action = fun () -> parseStrictTenDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a ten digit IdentityNumber." action testProp "pin with invalid month returns parsing error" <| fun (Gen.Pin.PinWithInvalidMonth str) -> toAction parseStrictTenDigits str.[2..] |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; " Invalid month"] @@ -102,9 +108,9 @@ let tests = toAction parseStrictTenDigits str.[2..] |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTenDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTenDigitsInSpecificYear (null, year) |> Expect.throwsWithType @@ -126,59 +132,58 @@ let tests = testList "invalid personal identity number - StrictMode.TwelveDigits" [ testProp "10 digit string without hyphen-delimiter" <| fun (Gen.Pin.ValidPin pin) -> - pin.To10DigitString() - |> removeHyphen - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." + let str = pin.To10DigitString() |> removeHyphen + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action - testProp "10 digit string mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) + testProp "10 digit string mixed with 'non-digits' except plus" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." + |> surroundEachChar charsWithoutPlus + + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action testProp "10 digit string with delimiter" <| fun (Gen.Pin.ValidPin pin) -> - pin.To10DigitString() - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - + let str = pin.To10DigitString() + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + testPropWithMaxTest 400 "10 digit string 'in specific year'" <| fun (Gen.Pin.ValidPin pin) -> let offset = rng.Next (0, 200) let year = pin.Year + offset - (pin.To10DigitStringInSpecificYear year, year) - |> toAction parseStrictTwelveDigitsInSpecificYear - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - - testProp "12 digit string mixed with 'non-digits'" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutDigits = - charArray - |> Array.filter (isDigit >> not) - pin.To12DigitString() - |> surroundEachChar charsWithoutDigits - |> toAction parseStrictTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." - - testPropWithMaxTest 400 "10 digit string without hyphen delimiter 'in specific year'" - <| fun (Gen.Pin.ValidPin pin) -> - let offset = rng.Next (0, 200) - let year = pin.Year + offset - let str = - pin.To10DigitStringInSpecificYear year - |> removeHyphen - toAction parseStrictTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." + let str = pin.To10DigitStringInSpecificYear year + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + + testProp "12 digit string mixed with 'non-digits'" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutDigits = charArray |> Array.filter (isDigit >> not) + let str = pin.To12DigitString() |> surroundEachChar charsWithoutDigits + let action = fun () -> parseStrictTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action + + testPropWithMaxTest 400 "10 digit string without hyphen delimiter 'in specific year'" <| fun (Gen.Pin.ValidPin pin) -> + let offset = rng.Next (0, 200) + let year = pin.Year + offset + let str = pin.To10DigitStringInSpecificYear year |> removeHyphen + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action test "null string throws" { toAction parseStrictTwelveDigits null @@ -186,16 +191,16 @@ let tests = |> ignore } testProp "empty string throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTwelveDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTwelveDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." ) + let action = fun () -> parseStrictTwelveDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a twelve digit IdentityNumber." action testProp "pin with invalid year returns parsing error" <| fun (Gen.Pin.PinWithInvalidYear str) -> toAction parseStrictTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -212,9 +217,9 @@ let tests = toAction parseStrictTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTwelveDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTwelveDigitsInSpecificYear (null, year) |> Expect.throwsWithType @@ -256,47 +261,42 @@ let tests = testList "invalid personal identity number - StrictMode.TenOrTwelveDigits" [ - testProp "string mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." - testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - let str = - pin.To10DigitString() - |> removeHyphen - |> (surroundEachChar charsWithoutPlus) - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." + testProp "string mixed with 'non-digits' except plus" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action + testProp "string without hyphen delimiter, mixed with 'non-digits' except plus" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> removeHyphen |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action test "null string throws" { toAction parseStrictTenOrTwelveDigits null |> Expect.throwsWithType |> ignore } testProp "empty string returns throws" <| fun (Gen.EmptyString str) -> - toAction parseStrictTenOrTwelveDigits str - |> Expect.throwsWithType - |> Expect.throwsWithMessage - "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action + testProp "invalid number of digits throws" <| fun (Gen.Digits digits) -> isInvalidNumberOfDigits digits ==> lazy - ( toAction parseStrictTenOrTwelveDigits digits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." ) + let action = fun () -> parseStrictTenOrTwelveDigits digits |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action testProp "pin with invalid year returns parsing error" <| fun (Gen.Pin.PinWithInvalidYear str) -> toAction parseStrictTenOrTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid year" ] @@ -313,35 +313,31 @@ let tests = toAction parseStrictTenOrTwelveDigits str |> Expect.throwsWithMessages [ "String was not recognized as a valid IdentityNumber."; "Invalid checksum" ] testProp "parseInSpecificYear with empty string throws" <| fun (Gen.EmptyString str, Gen.ValidYear year) -> - toAction parseStrictTenOrTwelveDigitsInSpecificYear (str, year) - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." + let action = fun () -> parseStrictTenOrTwelveDigitsInSpecificYear (str, year) |> ignore + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber. Cannot be empty string or whitespace." action testProp "parseInSpecificYear with null string throws" <| fun (Gen.ValidYear year) -> toAction parseStrictTenOrTwelveDigitsInSpecificYear (null, year) |> Expect.throwsWithType |> ignore - testProp "10 digit string mixed with 'non-digits' except plus" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutPlus = - let isDigitOrPlus (c:char) = "0123456789+".Contains c - charArray - |> Array.filter (isDigitOrPlus >> not) - pin.To10DigitString() - |> (surroundEachChar charsWithoutPlus) - |> toAction parseStrictTenOrTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." - - testProp "12 digit string mixed with 'non-digits'" - <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> - let charsWithoutDigits = - charArray - |> Array.filter (isDigit >> not) - pin.To12DigitString() - |> surroundEachChar charsWithoutDigits - |> toAction parseStrictTenOrTwelveDigits - |> Expect.throwsWithType - |> Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." + testProp "10 digit string mixed with 'non-digits' except plus" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutPlus = + let isDigitOrPlus (c:char) = "0123456789+".Contains c + charArray |> Array.filter (isDigitOrPlus >> not) + + let str = pin.To10DigitString() |> surroundEachChar charsWithoutPlus + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action + + testProp "12 digit string mixed with 'non-digits'" <| fun (Gen.Pin.ValidPin pin, Gen.Char100 charArray) -> + let charsWithoutDigits = charArray |> Array.filter (isDigit >> not) + let str = pin.To12DigitString() |> surroundEachChar charsWithoutDigits + let action = fun () -> parseStrictTenOrTwelveDigits str |> ignore + + Expect.throwsWithType action + Expect.throwsWithMessage "String was not recognized as a valid IdentityNumber." action ] ] diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PinTestHelpers.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PinTestHelpers.fs index 3a4e565..a28d366 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/PinTestHelpers.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/PinTestHelpers.fs @@ -17,9 +17,8 @@ let (|Even|Odd|) num = | _ -> Odd module Expect = - let throwsWithType<'texn> f = + let throwsWithType<'texn when 'texn :> exn> (f: unit -> _) = Expect.throwsT<'texn> f "Should throw with expected type" - f let throwsWithMessages (msgs: string list) f = Expect.throwsC diff --git a/test/ActiveLogin.Identity.Swedish.FSharp.Test/Program.fs b/test/ActiveLogin.Identity.Swedish.FSharp.Test/Program.fs index 48c9ad2..f913544 100644 --- a/test/ActiveLogin.Identity.Swedish.FSharp.Test/Program.fs +++ b/test/ActiveLogin.Identity.Swedish.FSharp.Test/Program.fs @@ -1,5 +1,21 @@ -open Expecto +open Expecto [] let main argv = - Tests.runTestsInAssembly defaultConfig argv + let allTests = + testList "All Tests" [ + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_Constructor.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_Constructor.tests + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_equality.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_equality.tests + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_hash.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_hash.tests + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_Parse.tests + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_ParseStrict.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_Parse.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_ParseStrict.tests + ActiveLogin.Identity.Swedish.FSharp.Test.PersonalIdentityNumber_Hints.tests + ActiveLogin.Identity.Swedish.FSharp.Test.CoordinationNumber_Hints.tests + ] + + runTestsWithCLIArgs [] [||] allTests diff --git a/test/ActiveLogin.Identity.Swedish.Test/ActiveLogin.Identity.Swedish.Test.csproj b/test/ActiveLogin.Identity.Swedish.Test/ActiveLogin.Identity.Swedish.Test.csproj index dfc5dec..30ef9f1 100644 --- a/test/ActiveLogin.Identity.Swedish.Test/ActiveLogin.Identity.Swedish.Test.csproj +++ b/test/ActiveLogin.Identity.Swedish.Test/ActiveLogin.Identity.Swedish.Test.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 true false @@ -9,13 +9,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers - +