FBSDKGamingServicesKit/FBSDKGamingServicesKitTests/TournamentFetcherTests.swift (237 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ @testable import FBSDKGamingServicesKit import FBSDKCoreKit import FBSDKCoreKit_Basics import TestTools import XCTest final class TournamentFetcherTests: XCTestCase { let factory = TestGraphRequestFactory() lazy var fetcher = TournamentFetcher(graphRequestFactory: factory) enum Keys { static let tournamentID = "id" static let tournamentEndTime = "tournament_end_time" static let tournamentTitle = "tournament_title" static let tournamentPayload = "tournament_payload" } enum Values { static let date = DateFormatter.format(ISODateString: "2021-09-24T18:03:47+0000") static let tournamentID = "4227416214015447" static let tournamentEndTime = "2021-09-24T18:03:47+0000" static let tournamentTitle = "test title" static let tournamentPayload = "test payload" } override func setUp() { super.setUp() AuthenticationToken.current = SampleAuthenticationToken.validToken(withGraphDomain: "gaming") AccessToken.current = SampleAccessTokens.validToken } override func tearDown() { AuthenticationToken.current = nil AccessToken.current = nil super.tearDown() } func testDependencies() { let fetcher = TournamentFetcher() XCTAssertTrue( fetcher.graphRequestFactory is GraphRequestFactory, "Should have a default GraphRequestFactory of the expected type" ) } func testCustomDependencies() { XCTAssertEqual( fetcher.graphRequestFactory as? TestGraphRequestFactory, factory, "Should be able to create with a custom graph request factory" ) } func testFetchTournaments() throws { fetcher.fetchTournaments { _ in XCTFail("Should not reach here") } let request = try XCTUnwrap(factory.capturedRequests.first) XCTAssertEqual( request.startCallCount, 1, "Should start the request to fetch tournaments" ) XCTAssertEqual( factory.capturedGraphPath, "user123/tournaments", "Should create a request with the expected graph path" ) XCTAssertEqual( factory.capturedParameters as? [String: String], [:], "Should create a request with the expected parameters" ) } func testFetchTournamentsAuthTokenWithInvalidGraphDomain() throws { var completionWasInvoked = false AuthenticationToken.current = SampleAuthenticationToken.validToken(withGraphDomain: "notGaming") fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case .invalidAuthToken = error else { return XCTFail("Was expecting invalid auth token error, instead recieved:\(error)") } case .success: XCTFail("Should not succeed") } completionWasInvoked = true } XCTAssert(completionWasInvoked) } func testFetchTournamentsWithoutAccessToken() throws { var completionWasInvoked = false AccessToken.current = nil fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case .invalidAccessToken = error else { return XCTFail("Was expecting invalid access token error, instead recieved:\(error)") } case .success: XCTFail("Should not succeed") } completionWasInvoked = true } XCTAssert(completionWasInvoked) } func testHandlingTournamentFetchError() throws { var completionWasInvoked = false fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case let .server(serverError) = error else { return XCTFail("Should not be a decoding error") } XCTAssertTrue(serverError is SampleError) case .success: XCTFail("Should not succeed") } completionWasInvoked = true } let completion = try XCTUnwrap(factory.capturedRequests.first?.capturedCompletionHandler) completion(nil, nil, SampleError()) XCTAssert(completionWasInvoked) } func testHandlingTournamentFetchInvalidGraphResponse() throws { var completionWasInvoked = false fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case .decoding = error else { return XCTFail( "An graph response should complete with a decoding error, instead received: \(error)" ) } case .success: XCTFail("Should not succeed") } completionWasInvoked = true } let completion = try XCTUnwrap(factory.capturedRequests.first?.capturedCompletionHandler) completion(nil, SampleTournamentResults.invalidGraphAPIResponse, nil) XCTAssert(completionWasInvoked) } func testHandlingTournamentFetchResultAndError() throws { var completionWasInvoked = false fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case let .server(serverError) = error else { return XCTFail("Should not be a decoding error") } XCTAssertTrue(serverError is SampleError) case .success: XCTFail("Should not succeed") } completionWasInvoked = true } let completion = try XCTUnwrap(factory.capturedRequests.first?.capturedCompletionHandler) completion(nil, SampleTournamentResults.validPartial, SampleError()) XCTAssert(completionWasInvoked) } func testHandlingTournamentFetchInvalidResult() throws { var completionWasInvoked = false fetcher.fetchTournaments { result in switch result { case let .failure(error): guard case .decoding = error else { return XCTFail( "An invalid result should complete with a decoding error, instead received: \(error)" ) } case .success: XCTFail("Should not succeed") } completionWasInvoked = true } let completion = try XCTUnwrap(factory.capturedRequests.first?.capturedCompletionHandler) completion(nil, SampleTournamentResults.missingIdentifier, nil) XCTAssert(completionWasInvoked) } func testHandlingTournamentFetchValidResult() throws { let date = try XCTUnwrap(Values.date) let expectedTournament = Tournament( identifier: Values.tournamentID, endTime: date, title: Values.tournamentTitle, payload: Values.tournamentPayload ) var completionWasInvoked = false fetcher.fetchTournaments { result in switch result { case let .failure(error): XCTFail("Unexpected error received: \(error)") case let .success(tournaments): guard let tournament = tournaments.first else { return XCTFail("Tournaments array was empty") } guard let expiration = tournament.endTime?.timeIntervalSince1970 else { return XCTFail("Tournament missing expiration") } XCTAssertEqual(tournament.identifier, expectedTournament.identifier) XCTAssertEqual( expiration, date.timeIntervalSince1970 ) XCTAssertEqual(tournament.title, expectedTournament.title) XCTAssertEqual(tournament.payload, expectedTournament.payload) } completionWasInvoked = true } let completion = try XCTUnwrap(factory.capturedRequests.first?.capturedCompletionHandler) completion(nil, SampleTournamentResults.validFull, nil) XCTAssert(completionWasInvoked) } enum SampleTournamentResults { static let validPartial = [ "data": [ [ Keys.tournamentTitle: Values.tournamentTitle, Keys.tournamentEndTime: Values.tournamentEndTime, Keys.tournamentID: Values.tournamentID, ], ], ] static let validFull = [ "data": [ [ Keys.tournamentTitle: Values.tournamentTitle, Keys.tournamentEndTime: Values.tournamentEndTime, Keys.tournamentID: Values.tournamentID, Keys.tournamentPayload: Values.tournamentPayload, ], ], ] static let missingIdentifier = [ "data": [ [ Keys.tournamentTitle: Values.tournamentTitle, Keys.tournamentEndTime: Values.tournamentEndTime, ], ], ] static let invalidGraphAPIResponse = ["not_data": []] } }