Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
66b743b
Migrate integration tests to in-process hosts via `WebApplicationFact…
Copilot May 17, 2026
1506a22
Enforce input/output kind safety for `ListOf`/`Nullable` wrappers at …
Copilot May 17, 2026
075018b
Pin CI workflows and build script to .NET SDK 10.0.300 (#578)
Copilot May 17, 2026
19d11c3
Pin CI workflows and build script to .NET SDK 10.0.301
xperiandri Jun 13, 2026
cc5fc0f
Fixed Repo Assist incorrectly encoded characters
xperiandri Jun 13, 2026
50b4569
Bump lodash and babel-cli in /samples/graphiql-client (#584)
dependabot[bot] Jun 13, 2026
d8aba70
Publish CI test results into PR discussions, harden artifact download…
Copilot Jun 13, 2026
45046d7
Fixed NuGet packaging of DesignTime DLL for F# provider
xperiandri Jun 13, 2026
e643b8d
Updated `FSharp.TypeProviders.SDK` to `8.10.0`
xperiandri Jun 13, 2026
bdd7297
fixup! Updated `FSharp.TypeProviders.SDK` to `8.10.0`
xperiandri Jun 14, 2026
15df50a
High severity vulnerability fix: upgrade `SQLitePCLRaw.lib.e_sqlite3`…
Copilot Jul 8, 2026
c1e8510
Support case-insensitive comparison with `ObjectListFilter` (#582)
Copilot Jul 9, 2026
2d94c67
`ObjectListFilter` filter values to target type coercion (#589)
xperiandri Jul 9, 2026
454a9e0
Migrated to modern `InternalsVisibleTo` syntax
xperiandri Jul 16, 2026
8e34237
Implemented support of `Guid` and value object scalars as `InputValue`
xperiandri Jul 17, 2026
78d21c1
Implemented tests for `ObjectListFilter` with empty arrays
xperiandri Aug 9, 2026
060fd26
Updated SDK to `10.0.302`
xperiandri Aug 9, 2026
d971701
Updated `Fantomas` to `7.0.5`
xperiandri Aug 9, 2026
eada5c2
Updated `FSDocs-Tools` to `22.1.0`
xperiandri Aug 9, 2026
b9ce3ad
Implemented robust interface field covariance validation & tests
xperiandri Aug 9, 2026
be74f88
Bump @protobufjs/utf8 from 1.1.0 to 1.1.1 in /samples/client-provider…
dependabot[bot] Aug 9, 2026
c072f8e
Bump brace-expansion from 1.1.14 to 1.1.18 in /samples/graphiql-clien…
dependabot[bot] Aug 10, 2026
7de55d4
Bump ws from 7.5.7 to 7.5.13 in /samples/client-provider/file-upload/…
dependabot[bot] Aug 11, 2026
28775fd
Bump websocket-driver from 0.7.0 to 0.7.5 in /samples/graphiql-client…
dependabot[bot] Aug 11, 2026
47f8300
Bump lodash from 4.17.21 to 4.18.1 in /samples/client-provider/file-u…
dependabot[bot] Aug 11, 2026
b86114c
Bump decode-uri-component from 0.2.0 to 0.2.2 in /samples/graphiql-cl…
dependabot[bot] Aug 11, 2026
ddf3b1a
Bump nanoid and shortid in /samples/client-provider/file-upload/serve…
dependabot[bot] Aug 11, 2026
1716ee8
Bump qs, http-server and express in /samples/graphiql-client
dependabot[bot] Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Migrate integration tests to in-process hosts via `WebApplicationFact…
…ory` and remove external server orchestration from build (#564)

Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Andrii Chebukin <XperiAndri@Outlook.com>
  • Loading branch information
3 people committed May 18, 2026
commit 66b743b6488a000bd5723f103d98ca418ec6970b
5 changes: 5 additions & 0 deletions FSharp.Data.GraphQL.Integration.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<Platform Name="x64" />
<Platform Name="x86" />
</Configurations>
<Folder Name="/samples/">
<Project Path="samples/star-wars-api/star-wars-api.fsproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path="Directory.Build.props" />
<File Path="Directory.Build.targets" />
Expand All @@ -12,7 +15,9 @@
<Folder Name="/src/">
<Project Path="src/FSharp.Data.GraphQL.Server.AspNetCore/FSharp.Data.GraphQL.Server.AspNetCore.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Giraffe/FSharp.Data.GraphQL.Server.Giraffe.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Middleware/FSharp.Data.GraphQL.Server.Middleware.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Oxpecker/FSharp.Data.GraphQL.Server.Oxpecker.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server.Relay/FSharp.Data.GraphQL.Server.Relay.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Server/FSharp.Data.GraphQL.Server.fsproj" />
<Project Path="src/FSharp.Data.GraphQL.Shared/FSharp.Data.GraphQL.Shared.fsproj" />
</Folder>
Expand Down
1 change: 1 addition & 0 deletions Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<PackageReference Update="GraphQL.Server.Ui.Voyager" Version="8.*" />
<PackageReference Update="HotChocolate.AspNetCore" Version="15.*" />
<PackageReference Update="Iced" Version="1.17.*" />
<PackageReference Update="Microsoft.AspNetCore.Mvc.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Update="Microsoft.Azure.Cosmos" Version="3.*" />
<PackageReference Update="Microsoft.CodeCoverage" Version="17.3.*" />
<PackageReference Update="Microsoft.Data.Sqlite" Version="$(MicrosoftExtensionsVersion)" />
Expand Down
72 changes: 11 additions & 61 deletions build/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ module Program

open System
open System.IO
open System.Net.Http
open System.Text.Json

open Fake.Core
open Fake.Core.TargetOperators
Expand Down Expand Up @@ -123,26 +121,6 @@ let runTests (project : string) (args : string) =
|> _.WithCommon(DotNetCli.setVersion))
project

let starWarsServerStream = StreamRef.Empty

let [<Literal>] StartStarWarsServerTarget = "StartStarWarsServer"
Target.create StartStarWarsServerTarget <| fun _ ->
Target.activateFinal "StopStarWarsServer"

let project =
"samples"
</> "star-wars-api"
</> "star-wars-api.fsproj"

startGraphQLServer project 8086 starWarsServerStream

let [<Literal>] StopStarWarsServerTarget = "StopStarWarsServer"
Target.createFinal StopStarWarsServerTarget <| fun _ ->
try
starWarsServerStream.Value.Write ([| 0uy |], 0, 1)
with e ->
printfn "%s" e.Message

let integrationTestServerProjectPath =
"tests"
</> "FSharp.Data.GraphQL.IntegrationTests.Server"
Expand Down Expand Up @@ -179,58 +157,35 @@ Target.createFinal StopIntegrationServerTarget <| fun _ ->
with e ->
printfn "%s" e.Message

let [<Literal>] UpdateIntrospectionFileTarget = "UpdateIntrospectionFile"
Target.create UpdateIntrospectionFileTarget <| fun _ ->
let client = new HttpClient ()
(task {
let! result = client.GetAsync ("http://localhost:8086")
let! contentStream = result.Content.ReadAsStreamAsync ()
let! jsonDocument = JsonDocument.ParseAsync contentStream
let file =
new FileStream ("tests/FSharp.Data.GraphQL.IntegrationTests/introspection.json", FileMode.Create, FileAccess.Write, FileShare.None)
let encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
let jsonWriterOptions = JsonWriterOptions (Indented = true, Encoder = encoder)
let writer = new Utf8JsonWriter (file, jsonWriterOptions)
jsonDocument.WriteTo writer
do! writer.FlushAsync ()
do! writer.DisposeAsync ()
do! file.DisposeAsync ()
result.Dispose ()
})
.Wait ()
client.Dispose ()

let unitTestsProjectPath =
"tests"
</> "FSharp.Data.GraphQL.Tests"
</> "FSharp.Data.GraphQL.Tests.fsproj"

let integrationTestsProjectPath =
"tests"
</> "FSharp.Data.GraphQL.IntegrationTests"
</> "FSharp.Data.GraphQL.IntegrationTests.fsproj"

let [<Literal>] BuildIntegrationTestsTarget = "BuildIntegrationTests"
Target.create BuildIntegrationTestsTarget <| fun _ ->
let [<Literal>] UpdateIntrospectionFileTarget = "UpdateIntrospectionFile"
Target.create UpdateIntrospectionFileTarget <| fun _ ->
integrationTestsProjectPath
|> DotNet.build (fun options -> {
|> DotNet.test (fun options -> {
options with
Framework = Some DotNetMoniker
Configuration = configuration
Common = { DotNetCli.setVersion options.Common with CustomParams = Some "--filter FullyQualifiedName~IntrospectionUpdateTests" }
MSBuildParams = {
options.MSBuildParams with
DisableInternalBinLog = true
Verbosity = Some Normal
}
Common = DotNetCli.setVersion options.Common
})

let unitTestsProjectPath =
"tests"
</> "FSharp.Data.GraphQL.Tests"
</> "FSharp.Data.GraphQL.Tests.fsproj"

let [<Literal>] RunUnitTestsTarget = "RunUnitTests"
Target.create RunUnitTestsTarget <| fun _ ->
runTests unitTestsProjectPath ""

let [<Literal>] RunIntegrationTestsTarget = "RunIntegrationTests"
Target.create RunIntegrationTestsTarget <| fun _ ->
runTests integrationTestsProjectPath "" //"--filter Execution=Sync"

let prepareDocGen () =
Shell.rm "docs/release-notes.md"
Shell.cp "RELEASE_NOTES.md" "docs/RELEASE_NOTES.md"
Expand Down Expand Up @@ -406,12 +361,7 @@ Target.create "PackAndPush" ignore
==> RestoreTarget
==> BuildTarget
==> RunUnitTestsTarget
==> StartStarWarsServerTarget
==> BuildIntegrationTestServerTarget
==> StartIntegrationServerTarget
==> UpdateIntrospectionFileTarget
==> BuildIntegrationTestsTarget
==> RunIntegrationTestsTarget
==> "All"
=?> (GenerateDocsTarget, Environment.environVar "GITHUB_ACTIONS" = "True")
|> ignore
Expand Down
6 changes: 6 additions & 0 deletions samples/star-wars-fabulous-client/StarWars.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
<Project Path="StarWars.Android/StarWars.Android.fsproj">
<BuildType Solution="Ad-Hoc|*" Project="Release" />
<BuildType Solution="AppStore|*" Project="Release" />
<Build Solution="*|Any CPU" Project="false" />
<Build Solution="*|ARM" Project="false" />
<Build Solution="*|iPhone" Project="false" />
<Build Solution="*|iPhoneSimulator" Project="false" />
<Build Solution="*|x64" Project="false" />
<Build Solution="*|x86" Project="false" />
<Deploy Solution="Debug|Any CPU" />
<Deploy Solution="Release|Any CPU" />
</Project>
Expand Down
5 changes: 4 additions & 1 deletion samples/star-wars-fabulous-client/StarWars/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ open FSharp.Data.GraphQL

module Commands =

type GraphQLApi = GraphQLProvider<"http://localhost:8086">
[<Literal>]
let IntrospectionPath = "../../../tests/FSharp.Data.GraphQL.IntegrationTests/introspection.json"

type GraphQLApi = GraphQLProvider<IntrospectionPath>
let GetCharactersData = GraphQLApi.Operation<"queries/FetchCharacters.graphql">()

type Character = GraphQLApi.Operations.FetchCharacters.Types.CharactersFields.Character
20 changes: 10 additions & 10 deletions samples/star-wars-fabulous-client/StarWars/StarWars.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
</PropertyGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.5.2" />
<PackageReference Update="FSharp.Core" VersionOverride="4.5.2" />
<!-- workaround for VSMac bug https://github.com/mono/monodevelop/pull/5137 -->
</ItemGroup>
<ItemGroup>
Expand All @@ -18,16 +18,16 @@
<Compile Include="Style.fs" />
<Compile Include="Common.fs" />
<None Include="queries\FetchCharacters.graphql" />
<PackageReference Include="Xamarin.Forms" Version="4.0.0.425677" />
<PackageReference Include="Xamarin.Essentials" Version="1.0.0" />
<PackageReference Include="Fabulous.Core" Version="0.35.0" />
<PackageReference Include="Fabulous.CustomControls" Version="0.35.0" />
<PackageReference Include="Fabulous.LiveUpdate" Version="0.35.0" />
<PackageReference Include="FSharp.Core" Version="4.6.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="FSharp.Data.GraphQL.Client" Version="1.0.1" />
<PackageReference Include="Xamarin.Forms" VersionOverride="4.0.0.425677" />
<PackageReference Include="Xamarin.Essentials" VersionOverride="1.0.0" />
<PackageReference Include="Fabulous.Core" VersionOverride="0.35.0" />
<PackageReference Include="Fabulous.CustomControls" VersionOverride="0.35.0" />
<PackageReference Include="Fabulous.LiveUpdate" VersionOverride="0.35.0" />
<PackageReference Include="FSharp.Core" VersionOverride="4.6.2" />
<PackageReference Include="Newtonsoft.Json" VersionOverride="13.0.1" />
<PackageReference Include="FSharp.Data.GraphQL.Client" VersionOverride="1.0.1" />
<Compile Include="CharacterDetailPage.fs" />
<Compile Include="MainPage.fs" />
<Compile Include="StarWars.fs" />
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
Expand All @@ -15,31 +16,37 @@

<ItemGroup>
<Content Include="introspection.json" />
<Content Include="integration-introspection.json" />
<Content Include="reserved_scalar_input_date_introspection.json" />
<Content Include="reserved_scalar_object_date_introspection.json" />
<None Include="operation.graphql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
<Compile Include="Helpers.fs" />
<Compile Include="TestHosts.fs" />
<Compile Include="OperationErrorTests.fs" />
<Compile Include="IntrospectionUpdateTests.fs" />
<Compile Include="ReservedScalarNameProviderTests.fs" />
<Compile Include="LocalProviderTests.fs" />
<Compile Include="LocalProviderWithOptionalParametersOnlyTests.fs" />
<Compile Include="SwapiLocalProviderTests.fs" />
<Compile Include="SwapiRemoteProviderTests.fs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\FSharp.Data.GraphQL.IntegrationTests.Server\FSharp.Data.GraphQL.IntegrationTests.Server.fsproj" />
<ProjectReference Include="..\..\samples\star-wars-api\star-wars-api.fsproj" />
</ItemGroup>

<ItemGroup>
<Reference Include="FSharp.Data.GraphQL.Client">
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Client\bin\Debug\netstandard2.0\FSharp.Data.GraphQL.Client.dll')">..\..\src\FSharp.Data.GraphQL.Client\bin\Debug\netstandard2.0\FSharp.Data.GraphQL.Client.dll</HintPath>
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Client\bin\Release\netstandard2.0\FSharp.Data.GraphQL.Client.dll')">..\..\src\FSharp.Data.GraphQL.Client\bin\Release\netstandard2.0\FSharp.Data.GraphQL.Client.dll</HintPath>
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Client\bin\$(Configuration)\netstandard2.0\FSharp.Data.GraphQL.Client.dll')">..\..\src\FSharp.Data.GraphQL.Client\bin\$(Configuration)\netstandard2.0\FSharp.Data.GraphQL.Client.dll</HintPath>
<HintPath Condition="Exists('..\..\bin\FSharp.Data.GraphQL.Client\netstandard2.0\FSharp.Data.GraphQL.Client.dll')">..\..\bin\FSharp.Data.GraphQL.Client\netstandard2.0\FSharp.Data.GraphQL.Client.dll</HintPath>
</Reference>
<Reference Include="FSharp.Data.GraphQL.Shared">
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Client\bin\Debug\netstandard2.0\FSharp.Data.GraphQL.Shared.dll')">..\..\src\FSharp.Data.GraphQL.Client\bin\Debug\netstandard2.0\FSharp.Data.GraphQL.Shared.dll</HintPath>
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Client\bin\Release\netstandard2.0\FSharp.Data.GraphQL.Shared.dll')">..\..\src\FSharp.Data.GraphQL.Client\bin\Release\netstandard2.0\FSharp.Data.GraphQL.Shared.dll</HintPath>
<HintPath Condition="Exists('..\..\bin\FSharp.Data.GraphQL.Client\netstandard2.0\FSharp.Data.GraphQL.Shared.dll')">..\..\bin\FSharp.Data.GraphQL.Client\netstandard2.0\FSharp.Data.GraphQL.Shared.dll</HintPath>
<HintPath Condition="Exists('..\..\src\FSharp.Data.GraphQL.Shared\bin\$(Configuration)\net10.0\FSharp.Data.GraphQL.Shared.dll')">..\..\src\FSharp.Data.GraphQL.Shared\bin\$(Configuration)\net10.0\FSharp.Data.GraphQL.Shared.dll</HintPath>
<HintPath Condition="Exists('..\..\bin\FSharp.Data.GraphQL.Shared\net10.0\FSharp.Data.GraphQL.Shared.dll')">..\..\bin\FSharp.Data.GraphQL.Shared\net10.0\FSharp.Data.GraphQL.Shared.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module FSharp.Data.GraphQL.IntegrationTests.IntrospectionUpdateTests

open System
open System.IO
open System.Net.Http.Json
open System.Text.Json
open System.Threading
open Xunit

let introspectionFilePath =
Path.Combine (__SOURCE_DIRECTORY__, "integration-introspection.json")
|> Path.GetFullPath

let normalizeJsonDocument options (document : JsonDocument) =
use buffer = new MemoryStream ()
use writer = new Utf8JsonWriter (buffer, options)
document.WriteTo writer
writer.Flush ()
buffer.Seek (0L, SeekOrigin.Begin) |> ignore
JsonDocument.Parse buffer

let parseAndNormalizeJsonAsync ct options stream = task {
let! document = JsonDocument.ParseAsync (stream, cancellationToken = ct)
return normalizeJsonDocument options document
}

let areSchemasEqual (document1 : JsonDocument) (document2 : JsonDocument) =
let schema1 = document1.RootElement.GetProperty("data").GetProperty ("__schema")
let schema2 = document2.RootElement.GetProperty("data").GetProperty ("__schema")
schema1.GetRawText () = schema2.GetRawText ()

let readDestinationDocumentAsync ct (stream : FileStream) = task {
try
let! document = JsonDocument.ParseAsync (stream, cancellationToken = ct)
return ValueSome document
with :? JsonException ->
return ValueNone
}

let updateIntrospectionFileAsync ct sourceStream = task {
use destinationStream =
new FileStream (introspectionFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)

let options = JsonWriterOptions (Indented = true)
let! sourceDocument = parseAndNormalizeJsonAsync ct options sourceStream
destinationStream.Seek (0L, SeekOrigin.Begin) |> ignore
let! destinationDocument = readDestinationDocumentAsync ct destinationStream

let shouldUpdate =
match destinationDocument with
| ValueNone -> true
| ValueSome document -> not (areSchemasEqual document sourceDocument)

if shouldUpdate then
destinationStream.Seek (0L, SeekOrigin.Begin) |> ignore
destinationStream.SetLength 0
use writer = new Utf8JsonWriter (destinationStream, options)
sourceDocument.WriteTo writer
writer.Flush ()

return shouldUpdate
}

[<Fact>]
let ``Get GraphQL introspection response returns schema`` () = task {
use httpClient = TestHosts.createIntegrationHttpClient ()
let! response = httpClient.GetFromJsonAsync<JsonElement> ("/", CancellationToken.None)
let schema = response.GetProperty("data").GetProperty ("__schema")
Assert.NotEqual (Unchecked.defaultof<JsonElement>, schema)
let hasErrors, _ = response.TryGetProperty "errors"
Assert.False hasErrors
}

[<Fact>]
let ``Update integration introspection file when schema changes`` () = task {
use httpClient = TestHosts.createIntegrationHttpClient ()
let! sourceStream = httpClient.GetStreamAsync ("/")
let! wasUpdated = updateIntrospectionFileAsync CancellationToken.None sourceStream
Assert.True (File.Exists introspectionFilePath)
if wasUpdated then
let! sourceStreamSecondRun = httpClient.GetStreamAsync ("/")
use sourceStreamForVerification = sourceStreamSecondRun
let! wasUpdatedSecondRun = updateIntrospectionFileAsync CancellationToken.None sourceStreamForVerification
Assert.False wasUpdatedSecondRun
}
Loading