diff --git a/FindingFalcon.xcodeproj/project.pbxproj b/FindingFalcon.xcodeproj/project.pbxproj index 1790aab..bc0d44c 100644 --- a/FindingFalcon.xcodeproj/project.pbxproj +++ b/FindingFalcon.xcodeproj/project.pbxproj @@ -68,6 +68,8 @@ EDE92DE02B97216000C6A055 /* SelectVehicleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE92DDF2B97216000C6A055 /* SelectVehicleView.swift */; }; EDE92DE22B9757B400C6A055 /* DestinationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE92DE12B9757B400C6A055 /* DestinationView.swift */; }; EDE92DE42B9779AF00C6A055 /* FindFalconPlanetsAndVehiclesWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE92DE32B9779AF00C6A055 /* FindFalconPlanetsAndVehiclesWorker.swift */; }; + EDFE181D2BA5A77C0085A0E8 /* DestinationViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDFE181C2BA5A77C0085A0E8 /* DestinationViewTests.swift */; }; + EDFE18252BA5C3140085A0E8 /* FindFalconInteractorErrorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDFE18242BA5C3140085A0E8 /* FindFalconInteractorErrorMock.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -144,6 +146,8 @@ EDE92DDF2B97216000C6A055 /* SelectVehicleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectVehicleView.swift; sourceTree = ""; }; EDE92DE12B9757B400C6A055 /* DestinationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestinationView.swift; sourceTree = ""; }; EDE92DE32B9779AF00C6A055 /* FindFalconPlanetsAndVehiclesWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindFalconPlanetsAndVehiclesWorker.swift; sourceTree = ""; }; + EDFE181C2BA5A77C0085A0E8 /* DestinationViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestinationViewTests.swift; sourceTree = ""; }; + EDFE18242BA5C3140085A0E8 /* FindFalconInteractorErrorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindFalconInteractorErrorMock.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -220,14 +224,13 @@ ED5C88332BA3625F00D97AE3 /* FindFalcon */ = { isa = PBXGroup; children = ( - ED5C88612BA4A58C00D97AE3 /* FindFalconDataModelTests.swift */, - ED5C88632BA4B79800D97AE3 /* FindFalconDataStoreTests.swift */, ED5C88572BA4823500D97AE3 /* FindFalconInteractorTests.swift */, - ED5C885F2BA4829100D97AE3 /* FindFalconPlanetsAndVehiclesWorkerTests.swift */, ED5C88592BA4824C00D97AE3 /* FindFalconPresenterTests.swift */, - ED5C885D2BA4828200D97AE3 /* FindFalconTokenWorkerTests.swift */, ED5C885B2BA4826900D97AE3 /* FindFalconViewTests.swift */, ED5C884C2BA451B400D97AE3 /* Mocks */, + EDFE18232BA5A8A80085A0E8 /* Models */, + EDFE181F2BA5A7AC0085A0E8 /* UIComponents */, + EDFE181E2BA5A78F0085A0E8 /* Workers */, ); path = FindFalcon; sourceTree = ""; @@ -257,6 +260,7 @@ isa = PBXGroup; children = ( ED5C884D2BA47D0F00D97AE3 /* FindFalconDisplayMock.swift */, + EDFE18242BA5C3140085A0E8 /* FindFalconInteractorErrorMock.swift */, ED5C884F2BA47D2200D97AE3 /* FindFalconInteractorMock.swift */, ED5C884A2BA4514D00D97AE3 /* FindFalconModelMocks.swift */, ED5C88552BA47E4100D97AE3 /* FindFalconPlanetsAndVehiclesWorkerMock.swift */, @@ -377,6 +381,32 @@ path = UIComponents; sourceTree = ""; }; + EDFE181E2BA5A78F0085A0E8 /* Workers */ = { + isa = PBXGroup; + children = ( + ED5C885F2BA4829100D97AE3 /* FindFalconPlanetsAndVehiclesWorkerTests.swift */, + ED5C885D2BA4828200D97AE3 /* FindFalconTokenWorkerTests.swift */, + ); + path = Workers; + sourceTree = ""; + }; + EDFE181F2BA5A7AC0085A0E8 /* UIComponents */ = { + isa = PBXGroup; + children = ( + EDFE181C2BA5A77C0085A0E8 /* DestinationViewTests.swift */, + ); + path = UIComponents; + sourceTree = ""; + }; + EDFE18232BA5A8A80085A0E8 /* Models */ = { + isa = PBXGroup; + children = ( + ED5C88612BA4A58C00D97AE3 /* FindFalconDataModelTests.swift */, + ED5C88632BA4B79800D97AE3 /* FindFalconDataStoreTests.swift */, + ); + path = Models; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -411,6 +441,8 @@ EDE92D912B95FEAF00C6A055 /* PBXTargetDependency */, ); name = FindingFalconTests; + packageProductDependencies = ( + ); productName = FindingFalconTests; productReference = EDE92D8F2B95FEAF00C6A055 /* FindingFalconTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -443,6 +475,8 @@ Base, ); mainGroup = EDE92D762B95FEAC00C6A055; + packageReferences = ( + ); productRefGroup = EDE92D802B95FEAC00C6A055 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -519,8 +553,10 @@ ED5C88502BA47D2200D97AE3 /* FindFalconInteractorMock.swift in Sources */, ED5C88542BA47E3100D97AE3 /* FindFalconTokenWorkerMock.swift in Sources */, ED5C88462BA44EF500D97AE3 /* FoundFalconViewTests.swift in Sources */, + EDFE181D2BA5A77C0085A0E8 /* DestinationViewTests.swift in Sources */, ED5C88352BA42AA700D97AE3 /* FoundFalconPresenterMock.swift in Sources */, ED5C88622BA4A58C00D97AE3 /* FindFalconDataModelTests.swift in Sources */, + EDFE18252BA5C3140085A0E8 /* FindFalconInteractorErrorMock.swift in Sources */, ED5C884E2BA47D0F00D97AE3 /* FindFalconDisplayMock.swift in Sources */, ED5C88642BA4B79800D97AE3 /* FindFalconDataStoreTests.swift in Sources */, ED5C88312BA3520A00D97AE3 /* ResponseHandlerTests.swift in Sources */, diff --git a/FindingFalcon/FindFalcon/FindFalconView.swift b/FindingFalcon/FindFalcon/FindFalconView.swift index 98fbdc6..526b6f5 100644 --- a/FindingFalcon/FindFalcon/FindFalconView.swift +++ b/FindingFalcon/FindFalcon/FindFalconView.swift @@ -17,9 +17,11 @@ struct FindFalconView: View { var interactor: FindFalconBusinessLogic? var router: FindFalconRouter? - @ObservedObject private var dataStore = FindFalconDataStore() - @ObservedObject private var dataModel = FindFalconDataModel() - + @ObservedObject var dataStore = FindFalconDataStore() + @ObservedObject var dataModel = FindFalconDataModel() + + var onError: (() -> Void)? + var body: some View { NavigationView { Form { @@ -57,7 +59,6 @@ struct FindFalconView: View { Task { await getPlanetsAndVehicles() await retrieveToken() - dataStore.isLoading = false } } .navigationTitle("Find Falcon") @@ -95,6 +96,7 @@ extension FindFalconView: FindFalconDisplayLogic { func displayToken(viewModel: FindingFalcon.RetrieveToken.ViewModel) { dataStore.token = viewModel.token + dataStore.isLoading = false } } @@ -115,13 +117,13 @@ extension FindFalconView { } } - private func startAgain() { + func startAgain() { dataModel.reset() dataModel.destinations.first?.planetList = dataStore.planetList dataModel.destinations.first?.vehicleList = dataStore.vehicleList } - private func showError(_ error: Error) { - print(error.localizedDescription) + func showError(_ error: Error) { + onError?() } } diff --git a/FindingFalcon/FindFalcon/Models/FindFalconDataStore.swift b/FindingFalcon/FindFalcon/Models/FindFalconDataStore.swift index a701daa..57a889c 100644 --- a/FindingFalcon/FindFalcon/Models/FindFalconDataStore.swift +++ b/FindingFalcon/FindFalcon/Models/FindFalconDataStore.swift @@ -12,4 +12,11 @@ final class FindFalconDataStore: ObservableObject { @Published var vehicleList: [Vehicle] = [] @Published var token: Token? @Published var isLoading = true + + required init(planetList: [Planet] = [], vehicleList: [Vehicle] = [], token: Token? = nil, isLoading: Bool = true) { + self.planetList = planetList + self.vehicleList = vehicleList + self.token = token + self.isLoading = isLoading + } } diff --git a/FindingFalcon/FindFalcon/UIComponents/DestinationView.swift b/FindingFalcon/FindFalcon/UIComponents/DestinationView.swift index a025252..32ec488 100644 --- a/FindingFalcon/FindFalcon/UIComponents/DestinationView.swift +++ b/FindingFalcon/FindFalcon/UIComponents/DestinationView.swift @@ -25,7 +25,7 @@ struct DestinationView: View { .frame(maxWidth: .infinity, alignment: .trailing) Spacer() Button(action:{ - onButtonSelect() + onSelectButton() }) { HStack(alignment: .center, spacing: 10) { Image(systemName: isSelected ? "chevron.up" : "chevron.down") @@ -41,7 +41,7 @@ struct DestinationView: View { Text(item.name) .frame(maxWidth: .infinity, alignment: .trailing) .onTapGesture { - updatePlanetList(item) + onSelectPlanet(item) } Divider() } @@ -49,13 +49,13 @@ struct DestinationView: View { } if destination.selectedPlanet != nil { ForEach(destination.vehicleList, id: \.self) { - SelectVehicleView(vehicle: $0, selectedVehicle: destination.selectedVehicle, onSelectVehicle: updateVehicleList) + SelectVehicleView(vehicle: $0, selectedVehicle: destination.selectedVehicle, onSelectVehicle: onSelectVehicle) } } } } - private func updateVehicleList(_ vehicle: Vehicle) { + func onSelectVehicle(_ vehicle: Vehicle) { // if vehicle is not available, return from here. guard vehicle.totalNo > 0 else { return @@ -72,13 +72,13 @@ struct DestinationView: View { onVehicleSelect?() } - private func updatePlanetList(_ planet: Planet) { + func onSelectPlanet(_ planet: Planet) { destination.selectedPlanet = planet isSelected = false onPlanetSelect?() } - private func onButtonSelect() { + func onSelectButton() { isSelected = !isSelected } } diff --git a/FindingFalconTests/FindFalcon/FindFalconViewTests.swift b/FindingFalconTests/FindFalcon/FindFalconViewTests.swift index 3967e6f..40d2123 100644 --- a/FindingFalconTests/FindFalcon/FindFalconViewTests.swift +++ b/FindingFalconTests/FindFalcon/FindFalconViewTests.swift @@ -9,6 +9,7 @@ import XCTest @testable import FindingFalcon final class FindFalconViewTests: XCTestCase { + @MainActor func test_retrieveToken() async { var view = FindFalconView() @@ -30,4 +31,128 @@ final class FindFalconViewTests: XCTestCase { XCTAssertTrue(interactor.getPlanetsAndVehiclesCalled) } + + @MainActor func test_DataStore_Vehicle_And_Planet_List() async throws { + let presenter = FindFalconPresenter() + let interactor = FindFalconInteractor() + + let vehicleName: String = .mockRandom() + let vehicle: FindingFalcon.LoadVehicles.Response = .mockRandom(name: vehicleName, totalNo: 1, maxDistance: 200, speed: 2) + + let planetName: String = .mockRandom() + let planet: FindingFalcon.LoadPlanets.Response = .mockRandom(name: planetName, distance: 300) + + let response: FindingFalcon.LoadPlanetsAndVehicles.Response = .mockRandom(planets: [planet], vehicles: [vehicle]) + let planetsAndVehiclesWorker = FindFalconPlanetsAndVehiclesWorkerMock(response: response) + + interactor.planetsAndVehiclesWorker = planetsAndVehiclesWorker + + var view = FindFalconView() + view.interactor = interactor + interactor.presenter = presenter + presenter.view = view + + XCTAssertEqual(view.dataStore.planetList, []) + XCTAssertEqual(view.dataStore.vehicleList, []) + XCTAssertEqual(view.dataModel.destinations.first?.planetList, []) + XCTAssertEqual(view.dataModel.destinations.first?.vehicleList, []) + + await view.getPlanetsAndVehicles() + + XCTAssertEqual(view.dataStore.planetList, [Planet(name: planetName, distance: 300)]) + XCTAssertEqual(view.dataStore.vehicleList, [Vehicle(name: vehicleName, totalNo: 1, maxDistance: 200, speed: 2)]) + XCTAssertEqual(view.dataModel.destinations.first?.planetList, [Planet(name: planetName, distance: 300)]) + XCTAssertEqual(view.dataModel.destinations.first?.vehicleList, [Vehicle(name: vehicleName, totalNo: 1, maxDistance: 200, speed: 2)]) + } + + @MainActor func test_DataStore_Token() async throws { + let presenter = FindFalconPresenter() + let interactor = FindFalconInteractor() + + let token: String = .mockRandom() + let response: FindingFalcon.RetrieveToken.Response = .mockRandom(token: token) + let tokenWorker = FindFalconTokenWorkerMock(response: response) + + interactor.tokenWorker = tokenWorker + + var view = FindFalconView() + view.interactor = interactor + interactor.presenter = presenter + presenter.view = view + + XCTAssertNil(view.dataStore.token) + + await view.retrieveToken() + + XCTAssertEqual(view.dataStore.token, Token(token: token)) + } + + @MainActor func test_DataStore_isLoading() async throws { + let presenter = FindFalconPresenter() + let interactor = FindFalconInteractor() + + let tokenWorker = FindFalconTokenWorkerMock() + + interactor.tokenWorker = tokenWorker + + var view = FindFalconView() + view.interactor = interactor + interactor.presenter = presenter + presenter.view = view + + XCTAssertTrue(view.dataStore.isLoading) + + await view.retrieveToken() + + XCTAssertFalse(view.dataStore.isLoading) + } + + @MainActor func test_DataFetch_onError() async throws { + let expectation = expectation(description: "Error should occur") + expectation.expectedFulfillmentCount = 2 + + let interactor = FindFalconInteractorErrorMock() + + var view = FindFalconView() + view.interactor = interactor + + view.onError = { + expectation.fulfill() + } + + await view.getPlanetsAndVehicles() + await view.retrieveToken() + + // xcodebuild on CI is not working. + // await self.fulfillment(of: [expectation], timeout: 0.5) + + waitForExpectations(timeout: 0.5) + } + + @MainActor func test_startAgain() async throws { + var view = FindFalconView() + + let vehicle1: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 1, maxDistance: 200, speed: 2) + let vehicle2: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 1, maxDistance: 200, speed: 2) + + let planet1: Planet = .mockRandom(name: .mockRandom(), distance: 300) + let planet2: Planet = .mockRandom(name: .mockRandom(), distance: 300) + + view.dataStore = .mockRandom(planetList: [planet1, planet2], vehicleList: [vehicle1, vehicle2]) + + let destination1: Destination = .mockRandom(name: .mockRandom(), planetList: [planet1, planet2], vehicleList: [vehicle1, vehicle2], selectedVehicle: vehicle1, selectedPlanet: planet2) + let destination2: Destination = .mockRandom(name: .mockRandom(), planetList: [planet1, planet2], vehicleList: [vehicle1, vehicle2], selectedVehicle: vehicle2, selectedPlanet: planet1) + view.dataModel = .mockRandom(destinations: [destination1, destination2]) + + view.startAgain() + + XCTAssertEqual(destination1.planetList, [planet1, planet2]) + XCTAssertEqual(destination1.vehicleList, [vehicle1, vehicle2]) + XCTAssertNil(destination1.selectedVehicle) + XCTAssertNil(destination1.selectedPlanet) + XCTAssertEqual(destination2.planetList, []) + XCTAssertEqual(destination2.vehicleList, []) + XCTAssertNil(destination2.selectedVehicle) + XCTAssertNil(destination2.selectedPlanet) + } } diff --git a/FindingFalconTests/FindFalcon/Mocks/FindFalconInteractorErrorMock.swift b/FindingFalconTests/FindFalcon/Mocks/FindFalconInteractorErrorMock.swift new file mode 100644 index 0000000..e907809 --- /dev/null +++ b/FindingFalconTests/FindFalcon/Mocks/FindFalconInteractorErrorMock.swift @@ -0,0 +1,20 @@ +// +// FindFalconInteractorErrorMock.swift +// FindingFalconTests +// +// Created by Pallab Maiti on 16/03/24. +// + +import Foundation +@testable import FindingFalcon + +class FindFalconInteractorErrorMock: FindFalconBusinessLogic { + + func retrieveToken() async throws { + throw APIError.noResponse + } + + func getPlanetsAndVehicles() async throws { + throw APIError.noResponse + } +} diff --git a/FindingFalconTests/FindFalcon/Mocks/ModelMocks.swift b/FindingFalconTests/FindFalcon/Mocks/ModelMocks.swift index 2ea5329..2a27eac 100644 --- a/FindingFalconTests/FindFalcon/Mocks/ModelMocks.swift +++ b/FindingFalconTests/FindFalcon/Mocks/ModelMocks.swift @@ -75,3 +75,18 @@ extension Token: AnyMockable { return Token(token: token) } } + +extension FindFalconDataStore: AnyMockable { + public static func mockAny() -> Self { + return mockRandom() + } + + static func mockRandom( + planetList: [Planet] = [.mockAny()], + vehicleList: [Vehicle] = [.mockAny()], + token: Token? = .mockAny(), + isLoading: Bool = .mockAny() + ) -> Self { + return .init(planetList: planetList, vehicleList: vehicleList, token: token, isLoading: isLoading) + } +} diff --git a/FindingFalconTests/FindFalcon/FindFalconDataModelTests.swift b/FindingFalconTests/FindFalcon/Models/FindFalconDataModelTests.swift similarity index 86% rename from FindingFalconTests/FindFalcon/FindFalconDataModelTests.swift rename to FindingFalconTests/FindFalcon/Models/FindFalconDataModelTests.swift index a12d925..768d767 100644 --- a/FindingFalconTests/FindFalcon/FindFalconDataModelTests.swift +++ b/FindingFalconTests/FindFalcon/Models/FindFalconDataModelTests.swift @@ -82,5 +82,21 @@ final class FindFalconDataModelTests: XCTestCase { XCTAssertEqual(destination2.vehicleList[0], vehicle1) XCTAssertEqual(destination2.vehicleList[1].totalNo, 0) XCTAssertEqual(destination2.vehicleList[2], vehicle3) + + + destination2.selectedPlanet = planet1 + destination2.selectedVehicle = vehicle1 + XCTAssertFalse(dataModel.shouldButtonDisabled) + + dataModel.reset() + + XCTAssertEqual(destination1.planetList, []) + XCTAssertEqual(destination1.vehicleList, []) + XCTAssertNil(destination1.selectedVehicle) + XCTAssertNil(destination1.selectedPlanet) + XCTAssertEqual(destination2.planetList, []) + XCTAssertEqual(destination2.vehicleList, []) + XCTAssertNil(destination2.selectedVehicle) + XCTAssertNil(destination2.selectedPlanet) } } diff --git a/FindingFalconTests/FindFalcon/FindFalconDataStoreTests.swift b/FindingFalconTests/FindFalcon/Models/FindFalconDataStoreTests.swift similarity index 100% rename from FindingFalconTests/FindFalcon/FindFalconDataStoreTests.swift rename to FindingFalconTests/FindFalcon/Models/FindFalconDataStoreTests.swift diff --git a/FindingFalconTests/FindFalcon/UIComponents/DestinationViewTests.swift b/FindingFalconTests/FindFalcon/UIComponents/DestinationViewTests.swift new file mode 100644 index 0000000..1951111 --- /dev/null +++ b/FindingFalconTests/FindFalcon/UIComponents/DestinationViewTests.swift @@ -0,0 +1,105 @@ +// +// DestinationViewTests.swift +// FindingFalconTests +// +// Created by Pallab Maiti on 16/03/24. +// + +import XCTest +@testable import FindingFalcon + +final class DestinationViewTests: XCTestCase { + func test_Vehicle_Should_Not_Select_When_TotalNo_Zero() { + let expectation = expectation(description: "Vehicle should not be selected") + expectation.isInverted = true + + // Given + let vehicle: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 0, maxDistance: 200, speed: 2) + let destination: Destination = .mockRandom(selectedVehicle: nil) + + let view = DestinationView(destination: destination, onVehicleSelect: expectation.fulfill) + + // When + view.onSelectVehicle(vehicle) + + // Then + XCTAssertNil(destination.selectedVehicle) + + waitForExpectations(timeout: 0.5) + } + + func test_Vehicle_Should_Not_Select_When_Planet_Distance_Less_Than_Vehicle_MaxDistance() { + let expectation = expectation(description: "Vehicle should not be selected") + expectation.isInverted = true + + // Given + let planet: Planet = .mockRandom(name: .mockRandom(), distance: 300) + let vehicle: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 1, maxDistance: 200, speed: 2) + let destination: Destination = .mockRandom(selectedVehicle: nil, selectedPlanet: planet) + + let view = DestinationView(destination: destination, onVehicleSelect: expectation.fulfill) + + // When + view.onSelectVehicle(vehicle) + + // Then + XCTAssertNil(destination.selectedVehicle) + + waitForExpectations(timeout: 0.5) + } + + func test_Vehicle_Should_Not_Select_When_It_Already_Selected() { + let expectation = expectation(description: "Vehicle should not be selected") + expectation.isInverted = true + + // Given + let vehicle: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 1, maxDistance: 200, speed: 2) + let destination: Destination = .mockRandom(selectedVehicle: vehicle) + + let view = DestinationView(destination: destination, onVehicleSelect: expectation.fulfill) + + // When + view.onSelectVehicle(vehicle) + + // Then + XCTAssertNotNil(destination.selectedVehicle) + + waitForExpectations(timeout: 0.5) + } + + func test_Vehicle_Should_be_Selected() { + let expectation = expectation(description: "Vehicle should be selected") + + // Given + let vehicle: Vehicle = .mockRandom(name: .mockRandom(), totalNo: 1, maxDistance: 200, speed: 2) + let planet: Planet = .mockRandom(name: .mockRandom(), distance: 200) + let destination: Destination = .mockRandom(selectedVehicle: nil, selectedPlanet: planet) + + let view = DestinationView(destination: destination, onVehicleSelect: expectation.fulfill) + + // When + view.onSelectVehicle(vehicle) + + // Then + XCTAssertEqual(destination.selectedVehicle, vehicle) + + waitForExpectations(timeout: 0.5) + } + + func test_Planet_Should_be_Selected() { + let expectation = expectation(description: "Planet should be selected") + + // Given + let planet: Planet = .mockRandom(name: .mockRandom(), distance: 200) + let destination: Destination = .mockRandom(selectedPlanet: nil) + let view = DestinationView(destination: destination, onPlanetSelect: expectation.fulfill) + + // When + view.onSelectPlanet(planet) + + // Then + XCTAssertEqual(destination.selectedPlanet, planet) + + waitForExpectations(timeout: 0.5) + } +} diff --git a/FindingFalconTests/FindFalcon/FindFalconPlanetsAndVehiclesWorkerTests.swift b/FindingFalconTests/FindFalcon/Workers/FindFalconPlanetsAndVehiclesWorkerTests.swift similarity index 100% rename from FindingFalconTests/FindFalcon/FindFalconPlanetsAndVehiclesWorkerTests.swift rename to FindingFalconTests/FindFalcon/Workers/FindFalconPlanetsAndVehiclesWorkerTests.swift diff --git a/FindingFalconTests/FindFalcon/FindFalconTokenWorkerTests.swift b/FindingFalconTests/FindFalcon/Workers/FindFalconTokenWorkerTests.swift similarity index 100% rename from FindingFalconTests/FindFalcon/FindFalconTokenWorkerTests.swift rename to FindingFalconTests/FindFalcon/Workers/FindFalconTokenWorkerTests.swift