Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .github/workflows/combine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ on:
# Combine sources
- 'FirebaseCombineSwift/**'

# Podspec
# Podspecs
- 'FirebaseCombineSwift.podspec'
- 'FirebaseFunctionsTestingSupport.podspec'

# This workflow
- '.github/workflows/combine.yml'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
runs-on: macos-11
strategy:
matrix:
target: [ios, tvos, macos]
target: [ios, tvos, macos, watchos]
steps:
- uses: actions/checkout@v2
- name: Setup Bundler
Expand Down
13 changes: 12 additions & 1 deletion FirebaseFunctions.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,19 @@ Cloud Functions for Firebase.
s.test_spec 'integration' do |int_tests|
int_tests.scheme = { :code_coverage => true }
int_tests.source_files = 'FirebaseFunctions/Tests/Integration/*.[mh]',
'FirebaseFunctions/Tests/Integration/*.plist',
'SharedTestUtilities/FIRAuthInteropFake*',
'SharedTestUtilities/FIRMessagingInteropFake*'
end

# Uncomment to use pod gen to run the Swift Integration tests. This can't be
# committed because of the dependency on the unpublished FirebaseFunctionsTestingSupport.
# Alternatively, use Swift Package Manager to run the swift integration tests locally.
#
# s.test_spec 'swift-integration' do |swift_int|
# swift_int.platforms = {:ios => '15.0', :osx => '12.0', :tvos => '15.0', :watchos => '8.0'}
# swift_int.scheme = { :code_coverage => true }
# swift_int.dependency 'FirebaseFunctionsTestingSupport'
# swift_int.source_files = 'FirebaseFunctions/Tests/SwiftIntegration/*',
# 'FirebaseTestingSupport/Functions/Sources/*'
# end
end
242 changes: 230 additions & 12 deletions FirebaseFunctions/Tests/SwiftIntegration/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,35 @@ class IntegrationTests: XCTestCase {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testDataAsync() async throws {
let input = [
"bool": true,
"int": 2 as Int32,
"long": 9_876_543_210,
"string": "four",
"array": [5 as Int32, 6 as Int32],
"null": nil,
] as [String: Any?]

let function = functions.httpsCallable("dataTest")
XCTAssertNotNil(function)

let result = try await function.call(input)
let data = try XCTUnwrap(result.data as? [String: Any])
let message = try XCTUnwrap(data["message"] as? String)
let long = try XCTUnwrap(data["long"] as? Int64)
let code = try XCTUnwrap(data["code"] as? Int32)
XCTAssertEqual(message, "stub response")
XCTAssertEqual(long, 420)
XCTAssertEqual(code, 42)
}
#endif

func testScalar() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("scalarTest")
Expand All @@ -82,11 +108,23 @@ class IntegrationTests: XCTestCase {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testScalarAsync() async throws {
let function = functions.httpsCallable("scalarTest")
XCTAssertNotNil(function)

let result = try await function.call(17 as Int16)
let data = try XCTUnwrap(result.data as? Int)
XCTAssertEqual(data, 76)
}
#endif

func testToken() {
// Recreate _functions with a token.
// Recreate functions with a token.
let functions = FunctionsFake(
projectID: "functions-integration-test",
region: "us-central1",
Expand All @@ -108,9 +146,30 @@ class IntegrationTests: XCTestCase {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testTokenAsync() async throws {
// Recreate functions with a token.
let functions = FunctionsFake(
projectID: "functions-integration-test",
region: "us-central1",
customDomain: nil,
withToken: "token"
)
functions.useLocalhost()

let function = functions.httpsCallable("FCMTokenTest")
XCTAssertNotNil(function)

let result = try await function.call([:])
let data = try XCTUnwrap(result.data) as? [String: Int]
XCTAssertEqual(data, [:])
}
#endif

func testFCMToken() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("FCMTokenTest")
Expand All @@ -125,9 +184,21 @@ class IntegrationTests: XCTestCase {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testFCMTokenAsync() async throws {
let function = functions.httpsCallable("FCMTokenTest")
XCTAssertNotNil(function)

let result = try await function.call([:])
let data = try XCTUnwrap(result.data) as? [String: Int]
XCTAssertEqual(data, [:])
}
#endif

func testNull() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("nullTest")
Expand All @@ -142,9 +213,51 @@ class IntegrationTests: XCTestCase {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testNullAsync() async throws {
let function = functions.httpsCallable("nullTest")
XCTAssertNotNil(function)

let result = try await function.call(nil)
let data = try XCTUnwrap(result.data) as? NSNull
XCTAssertEqual(data, NSNull())
}
#endif

// No parameters to call should be the same as passing nil.
func testParameterless() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("nullTest")
XCTAssertNotNil(function)
function.call { result, error in
do {
XCTAssertNil(error)
let data = try XCTUnwrap(result?.data) as? NSNull
XCTAssertEqual(data, NSNull())
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
}
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testParameterlessAsync() async throws {
let function = functions.httpsCallable("nullTest")
XCTAssertNotNil(function)

let result = try await function.call()
let data = try XCTUnwrap(result.data) as? NSNull
XCTAssertEqual(data, NSNull())
}
#endif

func testMissingResult() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("missingResultTest")
Expand All @@ -161,9 +274,26 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testMissingResultAsync() async throws {
let function = functions.httpsCallable("missingResultTest")
XCTAssertNotNil(function)
do {
_ = try await function.call(nil)
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("Response is missing data field.", error.localizedDescription)
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif

func testUnhandledError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("unhandledErrorTest")
Expand All @@ -180,9 +310,26 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testUnhandledErrorAsync() async throws {
let function = functions.httpsCallable("unhandledErrorTest")
XCTAssertNotNil(function)
do {
_ = try await function.call([])
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("INTERNAL", error.localizedDescription)
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif

func testUnknownError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("unknownErrorTest")
Expand All @@ -199,9 +346,26 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testUnknownErrorAsync() async throws {
let function = functions.httpsCallable("unknownErrorTest")
XCTAssertNotNil(function)
do {
_ = try await function.call([])
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("INTERNAL", error.localizedDescription)
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif

func testExplicitError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("explicitErrorTest")
Expand All @@ -220,9 +384,28 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testExplicitErrorAsync() async throws {
let function = functions.httpsCallable("explicitErrorTest")
XCTAssertNotNil(function)
do {
_ = try await function.call([])
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.outOfRange.rawValue, error.code)
XCTAssertEqual("explicit nope", error.localizedDescription)
XCTAssertEqual(["start": 10 as Int32, "end": 20 as Int32, "long": 30],
error.userInfo[FunctionsErrorDetailsKey] as! [String: Int32])
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif

func testHttpError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("httpErrorTest")
Expand All @@ -238,9 +421,25 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testHttpErrorAsync() async throws {
let function = functions.httpsCallable("httpErrorTest")
XCTAssertNotNil(function)
do {
_ = try await function.call([])
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.invalidArgument.rawValue, error.code)
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif

func testTimeout() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable("timeoutTest")
Expand All @@ -259,6 +458,25 @@ class IntegrationTests: XCTestCase {
}
}
XCTAssert(true)
waitForExpectations(timeout: 1)
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testTimeoutAsync() async throws {
let function = functions.httpsCallable("timeoutTest")
XCTAssertNotNil(function)
function.timeoutInterval = 0.05
do {
_ = try await function.call([])
} catch {
let error = try XCTUnwrap(error) as NSError
XCTAssertEqual(FunctionsErrorCode.deadlineExceeded.rawValue, error.code)
XCTAssertEqual("DEADLINE EXCEEDED", error.localizedDescription)
XCTAssertNil(error.userInfo[FunctionsErrorDetailsKey])
return
}
XCTAssertFalse(true, "Failed to throw error for missing result")
}
#endif
}
2 changes: 2 additions & 0 deletions FirebaseFunctionsTestingSupport.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Pod::Spec.new do |s|

s.source_files = [
base_dir + 'Sources/**/*.{m,mm,h}',
'SharedTestUtilities/FIRAuthInteropFake*',
'SharedTestUtilities/FIRMessagingInteropFake*'
]

s.public_header_files = base_dir + '**/*.h'
Expand Down