Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Generated models support the @defer directive #31

Merged
merged 23 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0a4e0db
Added supporting changes for deferred fragments
calvincestari Sep 5, 2023
3b6543a
Add tests to validate deferred inline fragment
calvincestari Sep 11, 2023
f14ee8b
Add tests to validate deferred named fragment
calvincestari Sep 11, 2023
123d98a
Another test
calvincestari Sep 12, 2023
83dba17
Add nested deferred inline fragment test
calvincestari Sep 12, 2023
0cc1391
Label is no longer required for named fragments
calvincestari Sep 14, 2023
14ba7d3
Added documentation
calvincestari Sep 14, 2023
d4afea7
Update Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet…
calvincestari Sep 14, 2023
ec4643a
Update Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet…
calvincestari Sep 14, 2023
0e7c48b
Fixed tests
calvincestari Sep 14, 2023
1df8903
Remove isDeferred from ScopeCondition
calvincestari Sep 20, 2023
57f5b0b
Add deferred collection to ScopeDescriptor
calvincestari Sep 20, 2023
42d5191
Fix test mocks
calvincestari Sep 20, 2023
ff9d579
Update operation template for deferred property
calvincestari Sep 20, 2023
1adb93d
Refactor for deferred named fragment spreads
calvincestari Sep 20, 2023
9b1808d
Combine deferred properties of IR built named fragments into operation
calvincestari Sep 20, 2023
9e7416e
Refactor scope descriptor evaluation
calvincestari Sep 22, 2023
7bc5f32
Add inline documentation
calvincestari Sep 22, 2023
d8c4ad8
Remove selection set template defer tests
calvincestari Sep 22, 2023
14559fd
Updated JS frontend bundle
calvincestari Sep 22, 2023
2faef51
Update graphql-js parsing response matchers
calvincestari Sep 22, 2023
df3e425
Add RootFieldBuilder tests
calvincestari Sep 22, 2023
eb9ffea
Fix compilation result for string arguments
calvincestari Sep 22, 2023
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
6 changes: 4 additions & 2 deletions Tests/ApolloCodegenInternalTestHelpers/IR+Mocking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ extension IR.Operation {

public static func mock(
definition: CompilationResult.OperationDefinition? = nil,
referencedFragments: OrderedSet<IR.NamedFragment> = []
referencedFragments: OrderedSet<IR.NamedFragment> = [],
hasDeferredFragments: Bool = false
) -> IR.Operation {
let definition = definition ?? .mock()
return IR.Operation.init(
Expand All @@ -114,7 +115,8 @@ extension IR.Operation {
givenAllTypesInSchema: .init([]))
])
),
referencedFragments: referencedFragments
referencedFragments: referencedFragments,
hasDeferredFragments: hasDeferredFragments
)
}

Expand Down
265 changes: 258 additions & 7 deletions Tests/ApolloCodegenTests/CodeGenIR/IRRootFieldBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ class IRRootFieldBuilderTests: XCTestCase {
var document: String!
var ir: IRBuilder!
var operation: CompilationResult.OperationDefinition!
var subject: IR.EntityField!
var computedReferencedFragments: IR.RootFieldBuilder.ReferencedFragments!
var result: IR.RootFieldBuilder.Result!

var subject: IR.EntityField! {
result.rootField
}
var computedReferencedFragments: IR.RootFieldBuilder.ReferencedFragments! {
result.referencedFragments
}

var schema: IR.Schema { ir.schema }

Expand All @@ -28,8 +34,7 @@ class IRRootFieldBuilderTests: XCTestCase {
schemaSDL = nil
document = nil
operation = nil
subject = nil
computedReferencedFragments = nil
result = nil
super.tearDown()
}

Expand All @@ -39,7 +44,7 @@ class IRRootFieldBuilderTests: XCTestCase {
ir = try .mock(schema: schemaSDL, document: document)
operation = try XCTUnwrap(ir.compilationResult.operations.first)

let result = IR.RootFieldBuilder.buildRootEntityField(
result = IR.RootFieldBuilder.buildRootEntityField(
forRootField: .mock(
"query",
type: .nonNull(.entity(operation.rootType)),
Expand All @@ -48,8 +53,6 @@ class IRRootFieldBuilderTests: XCTestCase {
onRootEntity: IR.Entity(source: .operation(operation)),
inIR: ir
)
subject = result.rootField
computedReferencedFragments = result.referencedFragments
}

// MARK: - Children Computation
Expand Down Expand Up @@ -4324,4 +4327,252 @@ class IRRootFieldBuilderTests: XCTestCase {
expect(self.computedReferencedFragments).to(equal(expected))
}

// MARK: - Deferred Fragments

func test__deferredFragments__givenNoDeferredFragment_hasDeferredFragmentsFalse() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
... on Dog {
species
}
}
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beFalse())
}

func test__deferredFragments__givenDeferredInlineFragment_hasDeferredFragmentsTrue() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
... on Dog @defer(label: "root") {
species
}
}
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beTrue())
}

func test__deferredFragments__givenDeferredInlineFragmentWithCondition_hasDeferredFragmentsTrue() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
... on Dog @defer(if: "a", label: "root") {
species
}
}
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beTrue())
}

func test__deferredFragments__givenDeferredInlineFragmentWithConditionFalse_hasDeferredFragmentsFalse() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
... on Dog @defer(if: false, label: "root") {
species
}
}
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beFalse())
}

func test__deferredFragments__givenDeferredNamedFragment_onDifferentTypeCase_hasDeferredFragmentsTrue() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
...DogFragment @defer
}
}

fragment DogFragment on Dog {
species
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beTrue())
}

func test__deferredFragments__givenDeferredInlineFragment_withinNamedFragment_hasDeferredFragmentsTrue() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}

interface Animal {
id: String
species: String
genus: String
}

type Dog implements Animal {
id: String
species: String
genus: String
name: String
}
"""

document = """
query TestOperation {
allAnimals {
__typename
id
...DogFragment
}
}

fragment DogFragment on Animal {
... on Dog @defer(label: "root") {
species
}
}
"""

// when
try buildSubjectRootField()

// then
expect(self.result.hasDeferredFragments).to(beTrue())
}

}
Loading