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

Integration tests Setup and Initial tests for Scalars #13473

Merged
merged 11 commits into from
Aug 12, 2024
5 changes: 0 additions & 5 deletions FirebaseDataConnect/Sources/CodecHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ public class CodecHelper<K: CodingKey> {
}
}



// MARK: Decoding

public func decode<T: Decodable>(_ type: T.Type, forKey: K,
Expand All @@ -63,8 +61,5 @@ public class CodecHelper<K: CodingKey> {
return try container.decode(type, forKey: forKey)
}



public init() {}
}

12 changes: 4 additions & 8 deletions FirebaseDataConnect/Sources/Internal/CodableHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import Foundation

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal protocol CodableConverter {
protocol CodableConverter {
associatedtype E: Encodable
associatedtype D: Decodable

Expand All @@ -24,8 +24,7 @@ internal protocol CodableConverter {
}

@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal class Int64CodableConverter: CodableConverter {

class Int64CodableConverter: CodableConverter {
func encode(input: Int64?) throws -> String? {
guard let input else {
return nil
Expand All @@ -47,15 +46,13 @@ internal class Int64CodableConverter: CodableConverter {
}
}


@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal class UUIDCodableConverter: CodableConverter {

class UUIDCodableConverter: CodableConverter {
func encode(input: UUID?) throws -> String? {
guard let input else {
return nil
}

let uuidNoDashString = convertToNoDashUUID(uuid: input)
return uuidNoDashString
}
Expand All @@ -68,7 +65,6 @@ internal class UUIDCodableConverter: CodableConverter {
}

return UUID(uuidString: dashesAddedUUID)

}

private func convertToNoDashUUID(uuid: UUID) -> String {
Expand Down
62 changes: 62 additions & 0 deletions FirebaseDataConnect/Tests/Integration/ConfigSetup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation

import FirebaseCore
import FirebaseDataConnect

enum KitchenSinkError: Error {
case configureFailed
}

actor ProjectConfigurator {
static let shared = ProjectConfigurator()

private init() {}

private var setupComplete = false

func configureProject(useDummyEngine: Bool = true) async throws {
guard !setupComplete else {
// setup already complete
return
}

guard let resourcePath = Bundle.module.resourcePath
else { throw KitchenSinkError.configureFailed }
let projectDirPath = URL(fileURLWithPath: resourcePath)
.appendingPathComponent("fdc-kitchensink/dataconnect").path

let configureBody = """
{
"service_id": "\(KitchenSinkClient.connectorConfig.serviceId)",
"config_directory": "\(projectDirPath)",
"use_dummy": \(useDummyEngine)
}'

"""

let configureUrl = URL(string: "http://127.0.0.1:3628/emulator/configure")!
var configureRequest = URLRequest(url: configureUrl)
configureRequest.httpMethod = "POST"

let (data, response) = try await URLSession.shared.upload(
for: configureRequest,
from: configureBody.data(using: .utf8)!
)
print("responseData \(response)")
setupComplete = true
}
}
195 changes: 192 additions & 3 deletions FirebaseDataConnect/Tests/Integration/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,199 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import Foundation
import XCTest

import FirebaseCore
@testable import FirebaseDataConnect

import XCTest
final class IntegrationTests: XCTestCase {
class func setupFirebaseApp() {
if FirebaseApp.app() == nil {
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "fdc-test"
FirebaseApp.configure(options: options)
}
}

override class func setUp() {
setupFirebaseApp()
DataConnect.kitchenSinkClient.useEmulator(port: 3628)
}

override func setUp(completion: @escaping ((any Error)?) -> Void) {
Task {
do {
try await ProjectConfigurator.shared.configureProject()
completion(nil)
} catch {
completion(error)
}
}
}

// test to confirm that we can assign an explicit UUID
func testSpecifiedUUID() async throws {
let specifiedUUID = UUID()
let result = try await DataConnect.kitchenSinkClient.createTestIdMutationRef(id: specifiedUUID)
.execute()
XCTAssertEqual(result.data.testId_insert.id, specifiedUUID)
}

// test for an auto generated UUID assignment
func testAutoId() async throws {
let result = try await DataConnect.kitchenSinkClient.createTestAutoIdMutationRef().execute()
_ = result.data.testAutoId_insert.id
// if we get till here - we have successfully got a UUID and decoded it. So test is successful
XCTAssert(true)
}

func testStandardScalar() async throws {
let standardScalarUUID = UUID()
let testText = "Hello Firebase World"
let testDecimal = Double.random(in: 10.0 ... 999.0)
let testInt = Int(Int32.random(in: Int32.min ... Int32.max))
// The following fails since server returns a different value.
// The value is outside the 32-bit range and GQL Int is 32-bits.
// Tracked internally with issue - b/358198261
// let testInt = -6196243450739521536
aashishpatil-g marked this conversation as resolved.
Show resolved Hide resolved

let executeResult = try await DataConnect.kitchenSinkClient.createStandardScalarMutationRef(
id: standardScalarUUID,
number: testInt,
text: testText,
decimal: testDecimal
).execute()

XCTAssertEqual(
executeResult.data.standardScalars_insert.id,
standardScalarUUID,
"UUID mismatch between specified and returned"
)

let queryResult = try await DataConnect.kitchenSinkClient
.getStandardScalarQueryRef(id: standardScalarUUID).execute()

let returnedDecimal = queryResult.data.standardScalars?.decimal
XCTAssertEqual(
returnedDecimal,
testDecimal,
"Decimal value mismatch between sent \(testDecimal) and received \(String(describing: returnedDecimal))"
)

let returnedNumber = queryResult.data.standardScalars?.number
XCTAssertEqual(
returnedNumber,
testInt,
"Int value mismatch between sent \(testInt) and received \(String(describing: returnedNumber))"
)

let returnedText = queryResult.data.standardScalars?.text
XCTAssertEqual(
returnedText,
testText,
"String value mismatch between sent \(testText) and received \(String(describing: returnedText))"
)
}

func testScalarBoundaries() async throws {
let scalaryBoundaryUUID = UUID()

let maxInt = Int(Int32.max)
let minInt = Int(Int32.min)
let maxFloat = Double.greatestFiniteMagnitude
let minFloat = Double.leastNormalMagnitude

_ = try await DataConnect.kitchenSinkClient.createScalarBoundaryMutationRef(
id: scalaryBoundaryUUID,
maxNumber: maxInt,
minNumber: minInt,
maxDecimal: maxFloat,
minDecimal: minFloat
).execute()

let queryResult = try await DataConnect.kitchenSinkClient
.getScalarBoundaryQueryRef(id: scalaryBoundaryUUID).execute()

let returnedMaxInt = queryResult.data.scalarBoundary?.maxNumber
XCTAssertEqual(
returnedMaxInt,
maxInt,
"Returned maxInt \(String(describing: returnedMaxInt)) is not same as sent \(maxInt)"
)

let returnedMinInt = queryResult.data.scalarBoundary?.minNumber
XCTAssertEqual(
returnedMinInt,
minInt,
"Returned minInt \(minInt) is not same as sent \(minInt)"
)

let returnedMaxFloat = queryResult.data.scalarBoundary?.maxDecimal
XCTAssertEqual(
returnedMaxFloat,
maxFloat,
"Returned maxFloat \(String(describing: returnedMaxFloat)) is not same as sent \(maxFloat)"
)

let returnedMinFloat = queryResult.data.scalarBoundary?.minDecimal
XCTAssertEqual(
returnedMinFloat,
minFloat,
"Returned minFloat \(String(describing: returnedMinFloat)) is not same as sent \(minFloat)"
)
}

func testLargeNum() async throws {
let largeNumUUID = UUID()
let largeNum = Int64.random(in: Int64.min ... Int64.max)
let largeNumMax = Int64.max
let largeNumMin = Int64.min

_ = try await DataConnect.kitchenSinkClient.createLargeNumMutationRef(
id: largeNumUUID,
num: largeNum,
maxNum: largeNumMax,
minNum: largeNumMin
).execute()

let result = try await DataConnect.kitchenSinkClient.getLargeNumQueryRef(id: largeNumUUID)
.execute()

let returnedLargeNum = result.data.largeIntType?.num
XCTAssertEqual(
returnedLargeNum,
largeNum,
"Int64 returned \(String(describing: returnedLargeNum)) does not match sent \(largeNum)"
)

let returnedMax = result.data.largeIntType?.maxNum
XCTAssertEqual(
returnedMax,
largeNumMax,
"Int64 max returned \(String(describing: returnedMax)) does not match sent \(largeNumMax)"
)

let returnedMin = result.data.largeIntType?.minNum
XCTAssertEqual(
returnedMin,
largeNumMin,
"Int64 min returned \(String(describing: returnedMin)) does not match sent \(largeNumMin)"
)
}

func testLocalDateSerialization() async throws {
let localDateUUID = UUID()
let ld = try LocalDate(localDateString: "2024-11-01")

_ = try await DataConnect.kitchenSinkClient.createLocalDateMutationRef(
id: localDateUUID,
localDate: ld
).execute()

class IntegrationTests: XCTestCase {}
let result = try await DataConnect.kitchenSinkClient.getLocalDateTypeQueryRef(id: localDateUUID)
.execute()
let returnedLd = result.data.localDateType?.localDate
XCTAssertEqual(ld, returnedLd)
}
}
28 changes: 28 additions & 0 deletions FirebaseDataConnect/Tests/Integration/KitchenSinkClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import FirebaseDataConnect
import Foundation

public extension DataConnect {
static var kitchenSinkClient: KitchenSinkClient = {
let dc = DataConnect.dataConnect(connectorConfig: KitchenSinkClient.connectorConfig)
return KitchenSinkClient(dataConnect: dc)
}()
}

public class KitchenSinkClient {
var dataConnect: DataConnect

public static let connectorConfig = ConnectorConfig(
serviceId: "fdc-kitchensink",
location: "us-central1",
connector: "kitchen-sink"
)

init(dataConnect: DataConnect) {
self.dataConnect = dataConnect
}

public func useEmulator(host: String = DataConnect.EmulatorDefaults.host,
port: Int = DataConnect.EmulatorDefaults.port) {
dataConnect.useEmulator(host: host, port: port)
}
}
Loading
Loading