From e9e3a7526b64c811af091ca5a59e2246db2cb781 Mon Sep 17 00:00:00 2001 From: Calvin Cestari Date: Fri, 31 Mar 2023 22:57:38 -0700 Subject: [PATCH] Fix inner entity access control for operation-based templates --- Apollo.xcodeproj/project.pbxproj | 4 + .../ApolloCodegenConfiguration.swift | 10 + .../Templates/FragmentTemplate.swift | 5 +- ...LocalCacheMutationDefinitionTemplate.swift | 5 +- .../OperationDefinitionTemplate.swift | 18 +- .../Templates/SelectionSetTemplate.swift | 40 ++- .../Templates/TemplateRenderer.swift | 14 +- .../MockTemplateRenderer.swift | 18 ++ .../Templates/FragmentTemplateTests.swift | 52 ++-- ...CacheMutationDefinitionTemplateTests.swift | 18 +- .../OperationDefinitionTemplateTests.swift | 18 +- ...efinitionTemplate_DocumentType_Tests.swift | 266 ++++++++++++++++-- .../SelectionSetTemplateTests.swift | 68 +++-- ...ectionSetTemplate_Initializers_Tests.swift | 202 +++++++++++-- ...SetTemplate_LocalCacheMutation_Tests.swift | 20 +- ...ionSetTemplate_RenderOperation_Tests.swift | 191 ++++++++++++- 16 files changed, 791 insertions(+), 158 deletions(-) create mode 100644 Tests/ApolloCodegenInternalTestHelpers/MockTemplateRenderer.swift diff --git a/Apollo.xcodeproj/project.pbxproj b/Apollo.xcodeproj/project.pbxproj index 2064cdf4fd..7ba00e3240 100644 --- a/Apollo.xcodeproj/project.pbxproj +++ b/Apollo.xcodeproj/project.pbxproj @@ -741,6 +741,7 @@ E660A4D529CAEA0F001EA373 /* MockInterceptorProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E660A4D429CAEA0F001EA373 /* MockInterceptorProvider.swift */; }; E6630B8C26F0639B002D9E41 /* MockNetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6D79AB926EC05290094434A /* MockNetworkSession.swift */; }; E6630B8E26F071F9002D9E41 /* SchemaRegistryApolloSchemaDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6630B8D26F071F9002D9E41 /* SchemaRegistryApolloSchemaDownloaderTests.swift */; }; + E66644F129D7D2AE005E9140 /* MockTemplateRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66644EF29D7D27C005E9140 /* MockTemplateRenderer.swift */; }; E669352B2803EE11004E1FFC /* CustomScalarTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E669352A2803EE11004E1FFC /* CustomScalarTemplate.swift */; }; E669352D2803EF67004E1FFC /* CustomScalarTemplateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E669352C2803EF67004E1FFC /* CustomScalarTemplateTests.swift */; }; E669352F2803F09C004E1FFC /* CustomScalarFileGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E669352E2803F09C004E1FFC /* CustomScalarFileGenerator.swift */; }; @@ -1912,6 +1913,7 @@ E660A4D229CA5890001EA373 /* MockHTTPResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockHTTPResponse.swift; sourceTree = ""; }; E660A4D429CAEA0F001EA373 /* MockInterceptorProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockInterceptorProvider.swift; sourceTree = ""; }; E6630B8D26F071F9002D9E41 /* SchemaRegistryApolloSchemaDownloaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemaRegistryApolloSchemaDownloaderTests.swift; sourceTree = ""; }; + E66644EF29D7D27C005E9140 /* MockTemplateRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTemplateRenderer.swift; sourceTree = ""; }; E669352A2803EE11004E1FFC /* CustomScalarTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomScalarTemplate.swift; sourceTree = ""; }; E669352C2803EF67004E1FFC /* CustomScalarTemplateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomScalarTemplateTests.swift; sourceTree = ""; }; E669352E2803F09C004E1FFC /* CustomScalarFileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomScalarFileGenerator.swift; sourceTree = ""; }; @@ -3832,6 +3834,7 @@ DE5FD5FE276922AA0033EE23 /* MockApolloCodegenConfiguration.swift */, E6BEEFA527FAB1C700D94FF4 /* MockFileGenerator.swift */, E6EFDD0C27E8377200B17FE5 /* MockFileTemplate.swift */, + E66644EF29D7D27C005E9140 /* MockTemplateRenderer.swift */, DE5B313F27A482C80051C9D3 /* Resources.swift */, DECD490E262F81BF00924527 /* Info.plist */, ); @@ -5719,6 +5722,7 @@ DEE2060B27E14498002B4B82 /* IR+InclusionConditionsMock.swift in Sources */, DE01451628A5A971000F6F18 /* MockValidationOptions.swift in Sources */, E6BF98FC272C8FFC00C1FED8 /* MockFileManager.swift in Sources */, + E66644F129D7D2AE005E9140 /* MockTemplateRenderer.swift in Sources */, E6BEEFA627FAB1C700D94FF4 /* MockFileGenerator.swift in Sources */, DECD4921262F81CE00924527 /* CodegenTestHelper.swift in Sources */, DEAFB78327064F6900BE02F3 /* MockGraphQLType.swift in Sources */, diff --git a/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift b/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift index f8962c59ab..902f7994e2 100644 --- a/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift +++ b/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift @@ -1005,7 +1005,17 @@ extension ApolloCodegenConfiguration.OutputOptions { } } +extension ApolloCodegenConfiguration.AccessModifier { + var swiftString: String { + switch self { + case .public: return "public " + case .internal: return "" + } + } +} + // MARK: - SelectionSetInitializers - Private Implementation + extension ApolloCodegenConfiguration.SelectionSetInitializers { struct Options: OptionSet, Codable, Equatable { let rawValue: Int diff --git a/Sources/ApolloCodegenLib/Templates/FragmentTemplate.swift b/Sources/ApolloCodegenLib/Templates/FragmentTemplate.swift index 9b864cad08..fd1c149a70 100644 --- a/Sources/ApolloCodegenLib/Templates/FragmentTemplate.swift +++ b/Sources/ApolloCodegenLib/Templates/FragmentTemplate.swift @@ -16,14 +16,15 @@ struct FragmentTemplate: TemplateRenderer { \(embeddedAccessControlModifier(target: target))\ struct \(fragment.name.firstUppercased): \(config.schemaNamespace.firstUppercased)\ .\(if: isMutable, "Mutable")SelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" \(fragment.definition.source) ""\" } \(SelectionSetTemplate( mutable: isMutable, generateInitializers: config.options.shouldGenerateSelectionSetInitializers(for: fragment), - config: config + config: config, + accessControlRenderer: { embeddedAccessControlModifier(target: target) }() ).BodyTemplate(fragment.rootField.selectionSet)) } diff --git a/Sources/ApolloCodegenLib/Templates/LocalCacheMutationDefinitionTemplate.swift b/Sources/ApolloCodegenLib/Templates/LocalCacheMutationDefinitionTemplate.swift index d5bd4cb02e..8dd2e55a21 100644 --- a/Sources/ApolloCodegenLib/Templates/LocalCacheMutationDefinitionTemplate.swift +++ b/Sources/ApolloCodegenLib/Templates/LocalCacheMutationDefinitionTemplate.swift @@ -13,7 +13,7 @@ struct LocalCacheMutationDefinitionTemplate: OperationTemplateRenderer { """ \(embeddedAccessControlModifier(target: target))\ class \(operation.definition.nameWithSuffix.firstUppercased): LocalCacheMutation { - public static let operationType: GraphQLOperationType = .\(operation.definition.operationType.rawValue) + static let operationType: GraphQLOperationType = .\(operation.definition.operationType.rawValue) \(section: VariableProperties(operation.definition.variables)) @@ -24,7 +24,8 @@ struct LocalCacheMutationDefinitionTemplate: OperationTemplateRenderer { \(SelectionSetTemplate( mutable: true, generateInitializers: config.options.shouldGenerateSelectionSetInitializers(for: operation), - config: config + config: config, + accessControlRenderer: { embeddedAccessControlModifier(target: target) }() ).render(for: operation)) } diff --git a/Sources/ApolloCodegenLib/Templates/OperationDefinitionTemplate.swift b/Sources/ApolloCodegenLib/Templates/OperationDefinitionTemplate.swift index 29405600df..d63bfe0e97 100644 --- a/Sources/ApolloCodegenLib/Templates/OperationDefinitionTemplate.swift +++ b/Sources/ApolloCodegenLib/Templates/OperationDefinitionTemplate.swift @@ -18,7 +18,8 @@ struct OperationDefinitionTemplate: OperationTemplateRenderer { operation.definition, identifier: operation.operationIdentifier, fragments: operation.referencedFragments, - config: config + config: config, + accessControlRenderer: { embeddedAccessControlModifier(target: target) }() )) \(section: VariableProperties(operation.definition.variables)) @@ -29,7 +30,8 @@ struct OperationDefinitionTemplate: OperationTemplateRenderer { \(SelectionSetTemplate( generateInitializers: config.options.shouldGenerateSelectionSetInitializers(for: operation), - config: config + config: config, + accessControlRenderer: { embeddedAccessControlModifier(target: target) }() ).render(for: operation)) } @@ -37,10 +39,12 @@ struct OperationDefinitionTemplate: OperationTemplateRenderer { } private func OperationDeclaration(_ operation: CompilationResult.OperationDefinition) -> TemplateString { + let accessControl = embeddedAccessControlModifier(target: target) + return """ - \(embeddedAccessControlModifier(target: target))\ + \(accessControl)\ class \(operation.nameWithSuffix.firstUppercased): \(operation.operationType.renderedProtocolName) { - public static let operationName: String = "\(operation.name)" + \(accessControl)static let operationName: String = "\(operation.name)" """ } @@ -49,13 +53,15 @@ struct OperationDefinitionTemplate: OperationTemplateRenderer { _ operation: CompilationResult.OperationDefinition, identifier: @autoclosure () -> String, fragments: OrderedSet, - config: ApolloCodegen.ConfigurationContext + config: ApolloCodegen.ConfigurationContext, + accessControlRenderer: @autoclosure () -> String ) -> TemplateString { let includeFragments = !fragments.isEmpty let includeDefinition = config.options.apqs != .persistedOperationsOnly return TemplateString(""" - public static let document: \(config.ApolloAPITargetName).DocumentType = .\(config.options.apqs.rendered)( + \(accessControlRenderer())\ + static let document: \(config.ApolloAPITargetName).DocumentType = .\(config.options.apqs.rendered)( \(if: config.options.apqs != .disabled, """ operationIdentifier: \"\(identifier())\"\(if: includeDefinition, ",") """) diff --git a/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift b/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift index ee5db29577..8990f10750 100644 --- a/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift +++ b/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift @@ -6,17 +6,20 @@ struct SelectionSetTemplate { let isMutable: Bool let generateInitializers: Bool let config: ApolloCodegen.ConfigurationContext + let accessControlRenderer: () -> String private let nameCache: SelectionSetNameCache init( mutable: Bool = false, generateInitializers: Bool, - config: ApolloCodegen.ConfigurationContext + config: ApolloCodegen.ConfigurationContext, + accessControlRenderer: @autoclosure @escaping () -> String ) { self.isMutable = mutable self.generateInitializers = generateInitializers self.config = config + self.accessControlRenderer = accessControlRenderer self.nameCache = SelectionSetNameCache(config: config) } @@ -25,7 +28,7 @@ struct SelectionSetTemplate { func render(for operation: IR.Operation) -> String { TemplateString( """ - public struct Data: \(SelectionSetType()) { + \(accessControlRenderer())struct Data: \(SelectionSetType()) { \(BodyTemplate(operation.rootField.selectionSet)) } """ @@ -37,7 +40,8 @@ struct SelectionSetTemplate { TemplateString( """ \(SelectionSetNameDocumentation(field.selectionSet)) - public struct \(field.formattedSelectionSetName(with: config.pluralizer)): \(SelectionSetType()) { + \(accessControlRenderer())\ + struct \(field.formattedSelectionSetName(with: config.pluralizer)): \(SelectionSetType()) { \(BodyTemplate(field.selectionSet)) } """ @@ -49,7 +53,8 @@ struct SelectionSetTemplate { TemplateString( """ \(SelectionSetNameDocumentation(inlineFragment)) - public struct \(inlineFragment.renderedTypeName): \(SelectionSetType(asInlineFragment: true)) { + \(accessControlRenderer())\ + struct \(inlineFragment.renderedTypeName): \(SelectionSetType(asInlineFragment: true)) { \(BodyTemplate(inlineFragment)) } """ @@ -114,9 +119,11 @@ struct SelectionSetTemplate { } private func DataFieldAndInitializerTemplate() -> String { - """ - public \(isMutable ? "var" : "let") __data: DataDict - public init(_dataDict: DataDict) { __data = _dataDict } + let accessControl = accessControlRenderer() + + return """ + \(accessControl)\(isMutable ? "var" : "let") __data: DataDict + \(accessControl)init(_dataDict: DataDict) { __data = _dataDict } """ } @@ -130,13 +137,14 @@ struct SelectionSetTemplate { pluralizer: config.pluralizer ) return """ - public typealias RootEntityType = \(rootEntityName) + \(accessControlRenderer())typealias RootEntityType = \(rootEntityName) """ } private func ParentTypeTemplate(_ type: GraphQLCompositeType) -> String { """ - public static var __parentType: \(config.ApolloAPITargetName).ParentType { \ + \(accessControlRenderer())\ + static var __parentType: \(config.ApolloAPITargetName).ParentType { \ \(GeneratedTypeReference(type)) } """ } @@ -156,7 +164,8 @@ struct SelectionSetTemplate { config.options.warningsOnDeprecatedUsage == .include ? [] : nil let selectionsTemplate = TemplateString(""" - public static var __selections: [\(config.ApolloAPITargetName).Selection] { [ + \(accessControlRenderer())\ + static var __selections: [\(config.ApolloAPITargetName).Selection] { [ \(if: shouldIncludeTypenameSelection(for: scope), ".field(\"__typename\", String.self),") \(renderedSelections(groupedSelections.unconditionalSelections, &deprecatedArguments), terminator: ",") \(groupedSelections.inclusionConditionGroups.map { @@ -293,7 +302,8 @@ struct SelectionSetTemplate { return """ \(documentation: field.underlyingField.documentation, config: config) \(deprecationReason: field.underlyingField.deprecationReason, config: config) - public var \(field.responseKey.firstLowercased.asFieldAccessorPropertyName): \ + \(accessControlRenderer())\ + var \(field.responseKey.firstLowercased.asFieldAccessorPropertyName): \ \(typeName(for: field, forceOptional: isConditionallyIncluded)) {\ \(if: isMutable, """ @@ -322,7 +332,7 @@ struct SelectionSetTemplate { private func InlineFragmentAccessorTemplate(_ inlineFragment: IR.SelectionSet) -> TemplateString { let typeName = inlineFragment.renderedTypeName return """ - public var \(typeName.firstLowercased): \(typeName)? {\ + \(accessControlRenderer())var \(typeName.firstLowercased): \(typeName)? {\ \(if: isMutable, """ @@ -345,7 +355,7 @@ struct SelectionSetTemplate { } return """ - public struct Fragments: FragmentContainer { + \(accessControlRenderer())struct Fragments: FragmentContainer { \(DataFieldAndInitializerTemplate()) \(ifLet: selections.direct?.fragments.values, { @@ -369,7 +379,7 @@ struct SelectionSetTemplate { !scope.matches(fragment.inclusionConditions.unsafelyUnwrapped) return """ - public var \(propertyName): \(typeName)\ + \(accessControlRenderer())var \(propertyName): \(typeName)\ \(if: isOptional, "?") {\ \(if: isMutable, """ @@ -393,7 +403,7 @@ struct SelectionSetTemplate { private func InitializerTemplate(_ selectionSet: IR.SelectionSet) -> TemplateString { return """ - public init( + \(accessControlRenderer())init( \(InitializerSelectionParametersTemplate(selectionSet)) ) { self.init(_dataDict: DataDict(data: [ diff --git a/Sources/ApolloCodegenLib/Templates/TemplateRenderer.swift b/Sources/ApolloCodegenLib/Templates/TemplateRenderer.swift index c2b33225fc..d62305cb79 100644 --- a/Sources/ApolloCodegenLib/Templates/TemplateRenderer.swift +++ b/Sources/ApolloCodegenLib/Templates/TemplateRenderer.swift @@ -156,13 +156,13 @@ extension TemplateRenderer { guard config.output.schemaTypes.isInModule else { switch config.output.schemaTypes.moduleType { case .embeddedInTarget(_, .public): - return "\(ApolloCodegenConfiguration.AccessModifier.public) " + return ApolloCodegenConfiguration.AccessModifier.public.swiftString case .embeddedInTarget(_, .internal), .swiftPackageManager, .other: - return "" + return ApolloCodegenConfiguration.AccessModifier.internal.swiftString } } - return "public " + return ApolloCodegenConfiguration.AccessModifier.public.swiftString } private var operationTypeEmbeddedAccessControlModifier: String { @@ -170,18 +170,18 @@ extension TemplateRenderer { case .inSchemaModule: return schemaTypeEmbeddedAccessControlModifier case .absolute(_, .public), .relative(_, .public): - return "\(ApolloCodegenConfiguration.AccessModifier.public) " + return ApolloCodegenConfiguration.AccessModifier.public.swiftString case .absolute(_, .internal), .relative(_, .internal): - return "" + return ApolloCodegenConfiguration.AccessModifier.internal.swiftString } } private var testMockTypeEmbeddedAccessControlModifier: String { switch config.config.output.testMocks { case .none, .absolute(_, .internal): - return "" + return ApolloCodegenConfiguration.AccessModifier.internal.swiftString case .swiftPackage, .absolute(_, .public): - return "\(ApolloCodegenConfiguration.AccessModifier.public) " + return ApolloCodegenConfiguration.AccessModifier.public.swiftString } } } diff --git a/Tests/ApolloCodegenInternalTestHelpers/MockTemplateRenderer.swift b/Tests/ApolloCodegenInternalTestHelpers/MockTemplateRenderer.swift new file mode 100644 index 0000000000..a49c4ba811 --- /dev/null +++ b/Tests/ApolloCodegenInternalTestHelpers/MockTemplateRenderer.swift @@ -0,0 +1,18 @@ +import Foundation +@testable import ApolloCodegenLib + +public struct MockTemplateRenderer: TemplateRenderer { + public var target: ApolloCodegenLib.TemplateTarget + public var template: ApolloCodegenLib.TemplateString + public var config: ApolloCodegenLib.ApolloCodegen.ConfigurationContext + + public init( + target: TemplateTarget, + template: TemplateString, + config: ApolloCodegen.ConfigurationContext + ) { + self.target = target + self.template = template + self.config = config + } +} diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/FragmentTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/FragmentTemplateTests.swift index 96bab4fd37..a05c4614b4 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/FragmentTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/FragmentTemplateTests.swift @@ -67,7 +67,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ struct TestFragment: TestSchema.SelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" fragment TestFragment on Query { __typename allAnimals { @@ -77,8 +77,8 @@ class FragmentTemplateTests: XCTestCase { } ""\" } - public let __data: DataDict - public init(_dataDict: DataDict) { __data = _dataDict } + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } """ // when @@ -104,7 +104,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ struct TestFragment: TestSchema.SelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" fragment testFragment on Query { """ @@ -166,7 +166,7 @@ class FragmentTemplateTests: XCTestCase { """ let expected = """ - public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Animal } + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Animal } """ // when @@ -196,7 +196,7 @@ class FragmentTemplateTests: XCTestCase { """ let expected = """ - public static var __parentType: ApolloAPI.ParentType { TestSchema.Interfaces.Animal } + static var __parentType: ApolloAPI.ParentType { TestSchema.Interfaces.Animal } """ // when @@ -230,7 +230,7 @@ class FragmentTemplateTests: XCTestCase { """ let expected = """ - public static var __parentType: ApolloAPI.ParentType { TestSchema.Unions.Animal } + static var __parentType: ApolloAPI.ParentType { TestSchema.Unions.Animal } """ // when @@ -253,17 +253,17 @@ class FragmentTemplateTests: XCTestCase { let expected = """ struct TestFragment: TestSchema.SelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" fragment TestFragment on Query { __typename } ""\" } - public let __data: DataDict - public init(_dataDict: DataDict) { __data = _dataDict } + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } - public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } - public static var __selections: [ApolloAPI.Selection] { [ + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + static var __selections: [ApolloAPI.Selection] { [ ] } } @@ -288,17 +288,17 @@ class FragmentTemplateTests: XCTestCase { let expected = """ struct TestFragment: TestSchema.SelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" fragment TestFragment on Animal { __typename } ""\" } - public let __data: DataDict - public init(_dataDict: DataDict) { __data = _dataDict } + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } - public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Animal } - public static var __selections: [ApolloAPI.Selection] { [ + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Animal } + static var __selections: [ApolloAPI.Selection] { [ .field("__typename", String.self), ] } } @@ -400,7 +400,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ - public init( + init( species: String ) { self.init(_dataDict: DataDict(data: [ @@ -445,7 +445,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ - public init( + init( species: String ) { self.init(_dataDict: DataDict(data: [ @@ -550,7 +550,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ - public init( + init( species: String ) { self.init(_dataDict: DataDict(data: [ @@ -614,7 +614,7 @@ class FragmentTemplateTests: XCTestCase { let expected = """ struct TestFragment: TestSchema.MutableSelectionSet, Fragment { - public static var fragmentDefinition: StaticString { ""\" + static var fragmentDefinition: StaticString { ""\" fragment TestFragment on Query { __typename allAnimals { @@ -647,15 +647,15 @@ class FragmentTemplateTests: XCTestCase { let expected = """ - public var __data: DataDict - public init(_dataDict: DataDict) { __data = _dataDict } + var __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } - public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } - public static var __selections: [ApolloAPI.Selection] { [ + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + static var __selections: [ApolloAPI.Selection] { [ .field("allAnimals", [AllAnimal]?.self), ] } - public var allAnimals: [AllAnimal]? { + var allAnimals: [AllAnimal]? { get { __data["allAnimals"] } set { __data["allAnimals"] = newValue } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/LocalCacheMutationDefinitionTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/LocalCacheMutationDefinitionTemplateTests.swift index 16ea19e6fd..e1da115f92 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/LocalCacheMutationDefinitionTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/LocalCacheMutationDefinitionTemplateTests.swift @@ -69,7 +69,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationLocalCacheMutation: LocalCacheMutation { - public static let operationType: GraphQLOperationType = .query + static let operationType: GraphQLOperationType = .query """ @@ -105,7 +105,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { let expected = """ class LowercaseOperationLocalCacheMutation: LocalCacheMutation { - public static let operationType: GraphQLOperationType = .query + static let operationType: GraphQLOperationType = .query """ @@ -131,7 +131,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationLocalCacheMutation: LocalCacheMutation { - public static let operationType: GraphQLOperationType = .query + static let operationType: GraphQLOperationType = .query """ @@ -171,7 +171,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationLocalCacheMutation: LocalCacheMutation { - public static let operationType: GraphQLOperationType = .mutation + static let operationType: GraphQLOperationType = .mutation """ @@ -211,7 +211,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationLocalCacheMutation: LocalCacheMutation { - public static let operationType: GraphQLOperationType = .subscription + static let operationType: GraphQLOperationType = .subscription """ @@ -228,8 +228,8 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { // given let expected = """ - public struct Data: TestSchema.MutableSelectionSet { - public var __data: DataDict + struct Data: TestSchema.MutableSelectionSet { + var __data: DataDict """ // when @@ -450,7 +450,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { """ } - public init( + init( """ config = ApolloCodegenConfiguration.mock( @@ -493,7 +493,7 @@ class LocalCacheMutationDefinitionTemplateTests: XCTestCase { """ } - public init( + init( """ config = ApolloCodegenConfiguration.mock( diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplateTests.swift index ab652b82bc..0cb9198101 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplateTests.swift @@ -69,7 +69,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationQuery: GraphQLQuery { - public static let operationName: String = "TestOperation" + static let operationName: String = "TestOperation" """ // when @@ -94,7 +94,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationQuery: GraphQLQuery { - public static let operationName: String = "TestOperationQuery" + static let operationName: String = "TestOperationQuery" """ // when @@ -133,7 +133,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationQueryMutation: GraphQLMutation { - public static let operationName: String = "TestOperationQuery" + static let operationName: String = "TestOperationQuery" """ // when @@ -172,7 +172,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationMutation: GraphQLMutation { - public static let operationName: String = "TestOperation" + static let operationName: String = "TestOperation" """ // when @@ -211,7 +211,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class TestOperationSubscription: GraphQLSubscription { - public static let operationName: String = "TestOperation" + static let operationName: String = "TestOperation" """ // when @@ -246,8 +246,8 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ class LowercaseOperationQuery: GraphQLQuery { - public static let operationName: String = "lowercaseOperation" - public static let document: ApolloAPI.DocumentType = .notPersisted( + static let operationName: String = "lowercaseOperation" + static let document: ApolloAPI.DocumentType = .notPersisted( definition: .init( #\"\"\" query lowercaseOperation($variable: String = "TestVar") { @@ -286,7 +286,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ - public init( + init( species: String ) { self.init(_dataDict: DataDict(data: [ @@ -332,7 +332,7 @@ class OperationDefinitionTemplateTests: XCTestCase { let expected = """ - public init( + init( species: String ) { self.init(_dataDict: DataDict(data: [ diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplate_DocumentType_Tests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplate_DocumentType_Tests.swift index 25f8032d67..9e8b4e5162 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplate_DocumentType_Tests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/OperationDefinitionTemplate_DocumentType_Tests.swift @@ -24,12 +24,39 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { operationIdentifier = nil } + func buildConfig( + moduleType: ApolloCodegenConfiguration.SchemaTypesFileOutput.ModuleType = .swiftPackageManager, + operations: ApolloCodegenConfiguration.OperationsFileOutput = .inSchemaModule, + queryStringLiteralFormat: ApolloCodegenConfiguration.QueryStringLiteralFormat = .singleLine, + apqs: ApolloCodegenConfiguration.APQConfig = .disabled, + cocoapodsCompatibleImportStatements: Bool = false + ) { + config = .mock( + output: .mock(moduleType: moduleType, operations: operations), + options: .init( + queryStringLiteralFormat: queryStringLiteralFormat, + apqs: apqs, + cocoapodsCompatibleImportStatements: cocoapodsCompatibleImportStatements + ) + ) + } + func renderDocumentType() throws -> String { - OperationDefinitionTemplate.DocumentType.render( + let config = ApolloCodegen.ConfigurationContext(config: config) + let mockTemplateRenderer = MockTemplateRenderer( + target: .operationFile, + template: "", + config: config + ) + + return OperationDefinitionTemplate.DocumentType.render( try XCTUnwrap(definition), identifier: operationIdentifier, fragments: referencedFragments ?? [], - config: ApolloCodegen.ConfigurationContext(config: config) + config: config, + accessControlRenderer: mockTemplateRenderer.embeddedAccessControlModifier( + target: mockTemplateRenderer.target + ) ).description } @@ -43,10 +70,11 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( queryStringLiteralFormat: .multiline, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -74,10 +102,11 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( queryStringLiteralFormat: .singleLine, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -101,10 +130,11 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( queryStringLiteralFormat: .multiline, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -132,10 +162,11 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( queryStringLiteralFormat: .singleLine, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -164,10 +195,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .multiline, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -201,10 +232,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .singleLine, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -234,10 +265,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .singleLine, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -275,10 +306,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .multiline, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -324,10 +355,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .singleLine, apqs: .disabled - )) + ) // when let actual = try renderDocumentType() @@ -354,10 +385,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .multiline, apqs: .automaticallyPersist - )) + ) // when let actual = try renderDocumentType() @@ -388,10 +419,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { } """ - config = .mock(options: .init( + buildConfig( queryStringLiteralFormat: .multiline, apqs: .persistedOperationsOnly - )) + ) // when let actual = try renderDocumentType() @@ -416,9 +447,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( cocoapodsCompatibleImportStatements: true - )) + ) // when let actual = try renderDocumentType() @@ -439,9 +471,10 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { name } """ - config = .mock(options: .init( + + buildConfig( cocoapodsCompatibleImportStatements: false - )) + ) // when let actual = try renderDocumentType() @@ -453,4 +486,181 @@ class OperationDefinitionTemplate_DocumentType_Tests: XCTestCase { """ expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) } + + // MARK: Access Level Tests + + func test__accessLevel__givenQuery_whenModuleTypeIsSwiftPackageManager_andOperationsInSchemaModule_shouldRenderWithPublicAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .swiftPackageManager, + operations: .inSchemaModule + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + public static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsEmbeddedInTargetWithPublicAccessModifier_andOperationsInSchemaModule_shouldRenderWithPublicAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .public), + operations: .inSchemaModule + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + public static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsEmbeddedInTargetWithInternalAccessModifier_andOperationsInSchemaModule_shouldRenderWithInternalAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .internal), + operations: .inSchemaModule + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsSwiftPackageManager_andOperationsRelativeWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .public) + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + public static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsSwiftPackageManager_andOperationsRelativeWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .internal) + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsSwiftPackageManager_andOperationsAbsoluteWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .public) + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + public static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__accessLevel__givenQuery_whenModuleTypeIsSwiftPackageManager_andOperationsAbsoluteWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + definition.source = + """ + query NameQuery { + name + } + """ + + buildConfig( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .internal) + ) + + // when + let actual = try renderDocumentType() + + // then + let expected = + """ + static let document: ApolloAPI.DocumentType = .notPersisted( + """ + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplateTests.swift index 248c54e38e..82d122a51d 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplateTests.swift @@ -37,7 +37,7 @@ class SelectionSetTemplateTests: XCTestCase { ir = try .mock(schema: schemaSDL, document: document) let operationDefinition = try XCTUnwrap(ir.compilationResult[operation: operationName]) operation = ir.build(operation: operationDefinition) - let config = ApolloCodegenConfiguration.mock( + let config = ApolloCodegen.ConfigurationContext(config: .mock( schemaNamespace: "TestSchema", output: configOutput, options: .init( @@ -46,10 +46,18 @@ class SelectionSetTemplateTests: XCTestCase { cocoapodsCompatibleImportStatements: cocoapodsImportStatements, warningsOnDeprecatedUsage: warningsOnDeprecatedUsage ) + )) + let mockTemplateRenderer = MockTemplateRenderer( + target: .operationFile, + template: "", + config: config ) subject = SelectionSetTemplate( generateInitializers: false, - config: ApolloCodegen.ConfigurationContext(config: config) + config: config, + accessControlRenderer: mockTemplateRenderer.embeddedAccessControlModifier( + target: mockTemplateRenderer.target + ) ) } @@ -491,15 +499,15 @@ class SelectionSetTemplateTests: XCTestCase { """ let tests: [ApolloCodegenConfiguration.FileOutput] = [ - .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)), - .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom")), + .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .swiftPackageManager, operations: .inSchemaModule), - .mock(moduleType: .other, operations: .relative(subpath: nil)), - .mock(moduleType: .other, operations: .absolute(path: "custom")), + .mock(moduleType: .other, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .other, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .other, operations: .inSchemaModule), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil)), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom")), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .inSchemaModule) + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom", accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .inSchemaModule) ] for test in tests { @@ -562,15 +570,15 @@ class SelectionSetTemplateTests: XCTestCase { """ let tests: [ApolloCodegenConfiguration.FileOutput] = [ - .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)), - .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom")), + .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .swiftPackageManager, operations: .inSchemaModule), - .mock(moduleType: .other, operations: .relative(subpath: nil)), - .mock(moduleType: .other, operations: .absolute(path: "custom")), + .mock(moduleType: .other, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .other, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .other, operations: .inSchemaModule), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil)), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom")), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .inSchemaModule) + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom", accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .inSchemaModule) ] for test in tests { @@ -2025,15 +2033,15 @@ class SelectionSetTemplateTests: XCTestCase { """ let tests: [ApolloCodegenConfiguration.FileOutput] = [ - .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)), - .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom")), + .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .swiftPackageManager, operations: .inSchemaModule), - .mock(moduleType: .other, operations: .relative(subpath: nil)), - .mock(moduleType: .other, operations: .absolute(path: "custom")), + .mock(moduleType: .other, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .other, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .other, operations: .inSchemaModule), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil)), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom")), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .inSchemaModule) + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom", accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .inSchemaModule) ] for test in tests { @@ -2093,15 +2101,15 @@ class SelectionSetTemplateTests: XCTestCase { """ let tests: [ApolloCodegenConfiguration.FileOutput] = [ - .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil)), - .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom")), + .mock(moduleType: .swiftPackageManager, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .swiftPackageManager, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .swiftPackageManager, operations: .inSchemaModule), - .mock(moduleType: .other, operations: .relative(subpath: nil)), - .mock(moduleType: .other, operations: .absolute(path: "custom")), + .mock(moduleType: .other, operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .other, operations: .absolute(path: "custom", accessModifier: .public)), .mock(moduleType: .other, operations: .inSchemaModule), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil)), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom")), - .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .inSchemaModule) + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .relative(subpath: nil, accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget"), operations: .absolute(path: "custom", accessModifier: .public)), + .mock(moduleType: .embeddedInTarget(name: "CustomTarget", accessModifier: .public), operations: .inSchemaModule) ] for test in tests { diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_Initializers_Tests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_Initializers_Tests.swift index d07aab2022..7a53841e8c 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_Initializers_Tests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_Initializers_Tests.swift @@ -25,39 +25,46 @@ class SelectionSetTemplate_Initializers_Tests: XCTestCase { } // MARK: - Helpers - + func buildSubjectAndOperation( - named operationName: String = "TestOperation" + named operationName: String = "TestOperation", + schemaNamespace: String = "TestSchema", + moduleType: ApolloCodegenConfiguration.SchemaTypesFileOutput.ModuleType = .swiftPackageManager, + operations: ApolloCodegenConfiguration.OperationsFileOutput = .inSchemaModule ) throws { ir = try .mock(schema: schemaSDL, document: document) let operationDefinition = try XCTUnwrap(ir.compilationResult[operation: operationName]) operation = ir.build(operation: operationDefinition) let config = ApolloCodegenConfiguration.mock( - schemaNamespace: "TestSchema", + schemaNamespace: schemaNamespace, + output: .mock(moduleType: moduleType, operations: operations), options: .init() ) + let mockTemplateRenderer = MockTemplateRenderer( + target: .operationFile, + template: "", + config: .init(config: config) + ) subject = SelectionSetTemplate( generateInitializers: true, - config: ApolloCodegen.ConfigurationContext(config: config) + config: ApolloCodegen.ConfigurationContext(config: config), + accessControlRenderer: mockTemplateRenderer.embeddedAccessControlModifier( + target: mockTemplateRenderer.target + ) ) } - - // MARK: - Tests - - // MARK: Object Type Tests - - func test__render_givenSelectionSetOnObjectType_parametersDoNotIncludeTypenameFieldAndObjectTypeIsRenderedDirectly() throws { - // given + + func buildSimpleObjectSchemaAndDocument() { schemaSDL = """ type Query { allAnimals: [Animal!] } - + type Animal { species: String! } """ - + document = """ query TestOperation { allAnimals { @@ -65,6 +72,169 @@ class SelectionSetTemplate_Initializers_Tests: XCTestCase { } } """ + } + + // MARK: - Access Level Tests + + func test__render__givenSelectionSet_whenModuleType_swiftPackageManager_andOperations_inSchemaModule_shouldRenderWithPublicAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + public init( + """ + + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .inSchemaModule + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_EmbededInTargetWithPublicAccessModifier_andOperations_inSchemaModule_shouldRenderWithPublicAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + public init( + """ + + try buildSubjectAndOperation( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .public), + operations: .inSchemaModule + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_EmbededInTargetWithInternalAccessModifier_andOperations_inSchemaModule_shouldRenderWithInternalAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + init( + """ + + try buildSubjectAndOperation( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .internal), + operations: .inSchemaModule + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_swiftPackageManager_andOperations_relativeWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + public init( + """ + + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .public) + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_swiftPackageManager_andOperations_relativeWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + init( + """ + + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .internal) + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_swiftPackageManager_andOperations_absoluteWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + public init( + """ + + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .public) + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + func test__render__givenSelectionSet_whenModuleType_swiftPackageManager_andOperations_absoluteWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + buildSimpleObjectSchemaAndDocument() + + let expected = """ + init( + """ + + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .internal) + ) + + let basic = try XCTUnwrap( + operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField + ) + + let actual = subject.render(field: basic) + + expect(actual).to(equalLineByLine(expected, atLine: 16, ignoringExtraLines: true)) + } + + // MARK: Object Type Tests + + func test__render_givenSelectionSetOnObjectType_parametersDoNotIncludeTypenameFieldAndObjectTypeIsRenderedDirectly() throws { + // given + buildSimpleObjectSchemaAndDocument() let expected = """ @@ -100,12 +270,12 @@ class SelectionSetTemplate_Initializers_Tests: XCTestCase { type Query { allAnimals: [Animal!] } - + interface Animal { species: String! } """ - + document = """ query TestOperation { allAnimals { @@ -113,7 +283,7 @@ class SelectionSetTemplate_Initializers_Tests: XCTestCase { } } """ - + let expected = """ public init( diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_LocalCacheMutation_Tests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_LocalCacheMutation_Tests.swift index 67ce0c241e..7ab3e65610 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_LocalCacheMutation_Tests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_LocalCacheMutation_Tests.swift @@ -28,15 +28,31 @@ class SelectionSetTemplate_LocalCacheMutationTests: XCTestCase { func buildSubjectAndOperation( schemaNamespace: String = "TestSchema", - named operationName: String = "TestOperation" + named operationName: String = "TestOperation", + moduleType: ApolloCodegenConfiguration.SchemaTypesFileOutput.ModuleType = .swiftPackageManager, + operations: ApolloCodegenConfiguration.OperationsFileOutput = .inSchemaModule ) throws { ir = try .mock(schema: schemaSDL, document: document) let operationDefinition = try XCTUnwrap(ir.compilationResult[operation: operationName]) operation = ir.build(operation: operationDefinition) + let config = ApolloCodegen.ConfigurationContext( + config: .mock( + schemaNamespace: schemaNamespace, + output: .mock(moduleType: moduleType, operations: operations) + ) + ) + let mockTemplateRenderer = MockTemplateRenderer( + target: .operationFile, + template: "", + config: config + ) subject = SelectionSetTemplate( mutable: true, generateInitializers: false, - config: .init(config: .mock(schemaNamespace: schemaNamespace)) + config: config, + accessControlRenderer: mockTemplateRenderer.embeddedAccessControlModifier( + target: mockTemplateRenderer.target + ) ) } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_RenderOperation_Tests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_RenderOperation_Tests.swift index 18ee0cbb87..5e9d24767f 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_RenderOperation_Tests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/SelectionSet/SelectionSetTemplate_RenderOperation_Tests.swift @@ -26,20 +26,32 @@ class SelectionSetTemplate_RenderOperation_Tests: XCTestCase { // MARK: - Helpers - func buildSubjectAndOperation(named operationName: String = "TestOperation") throws { + func buildSubjectAndOperation( + named operationName: String = "TestOperation", + moduleType: ApolloCodegenConfiguration.SchemaTypesFileOutput.ModuleType = .swiftPackageManager, + operations: ApolloCodegenConfiguration.OperationsFileOutput = .inSchemaModule + ) throws { ir = try .mock(schema: schemaSDL, document: document) let operationDefinition = try XCTUnwrap(ir.compilationResult[operation: operationName]) operation = ir.build(operation: operationDefinition) + let config = ApolloCodegen.ConfigurationContext(config: .mock( + output: .mock(moduleType: moduleType, operations: operations) + )) + let mockTemplateRenderer = MockTemplateRenderer( + target: .operationFile, + template: "", + config: config + ) subject = SelectionSetTemplate( generateInitializers: false, - config: ApolloCodegen.ConfigurationContext(config: .mock()) + config: config, + accessControlRenderer: mockTemplateRenderer.embeddedAccessControlModifier( + target: mockTemplateRenderer.target + ) ) } - // MARK: - Tests - - func test__render__givenOperationWithName_rendersDeclaration() throws { - // given + func buildSchemaAndDocument() { schemaSDL = """ type Query { allAnimals: [Animal!] @@ -57,6 +69,13 @@ class SelectionSetTemplate_RenderOperation_Tests: XCTestCase { } } """ + } + + // MARK: - Tests + + func test__render__givenOperationWithName_rendersDeclaration() throws { + // given + buildSchemaAndDocument() let expected = """ public struct Data: TestSchema.SelectionSet { @@ -75,4 +94,164 @@ class SelectionSetTemplate_RenderOperation_Tests: XCTestCase { expect(String(actual.reversed())).to(equalLineByLine("}", ignoringExtraLines: true)) } + // MARK: Access Level Tests + + func test__render__givenOperation_whenModuleType_swiftPackageManager_andOperations_inSchemaModule_shouldRenderWithPublicAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + public struct Data: TestSchema.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation(moduleType: .swiftPackageManager, operations: .inSchemaModule) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_embeddedInTargetWithPublicAccessModifier_andOperations_inSchemaModule_shouldRenderWithPublicAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + public struct Data: TestSchema.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .public), + operations: .inSchemaModule + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_embeddedInTargetWithInternalAccessModifier_andOperations_inSchemaModule_shouldRenderWithInternalAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + struct Data: TestSchema.SelectionSet { + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } + + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .embeddedInTarget(name: "TestTarget", accessModifier: .internal), + operations: .inSchemaModule + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_swiftPackageManager_andOperations_relativeWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + public struct Data: TestSchema.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .public) + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_swiftPackageManager_andOperations_relativeWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + struct Data: TestSchema.SelectionSet { + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } + + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .relative(subpath: nil, accessModifier: .internal) + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_swiftPackageManager_andOperations_absoluteWithPublicAccessModifier_shouldRenderWithPublicAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + public struct Data: TestSchema.SelectionSet { + public let __data: DataDict + public init(_dataDict: DataDict) { __data = _dataDict } + + public static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .public) + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + + func test__render__givenOperation_whenModuleType_swiftPackageManager_andOperations_absoluteWithInternalAccessModifier_shouldRenderWithInternalAccess() throws { + // given + buildSchemaAndDocument() + + let expected = """ + struct Data: TestSchema.SelectionSet { + let __data: DataDict + init(_dataDict: DataDict) { __data = _dataDict } + + static var __parentType: ApolloAPI.ParentType { TestSchema.Objects.Query } + """ + + // when + try buildSubjectAndOperation( + moduleType: .swiftPackageManager, + operations: .absolute(path: "", accessModifier: .internal) + ) + let actual = subject.render(for: operation) + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + }