From 5188d63ffc3b0b86c20298ef98e51fb3c3d8c80c Mon Sep 17 00:00:00 2001 From: Jack Alto <384288+aokj4ck@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:58:15 -0500 Subject: [PATCH] Update tests to remove reliance on UserDefaults (#156) ### Description - Remove all usages of UserDefaults from MapboxSearch and MapboxSearchUI - Replaces this with plain dependency injection - Add LocalhostMockServiceProvider for integration tests to provide a mocked customBaseURL - Add FeedbackIntegrationTestCase back to UI test suite - Split MockServerTestCase into UI and Integration variants because it had a namespace collision - Utilize customBaseURL for ServiceProvider and LocalhostMockServiceProvider - Stop reading from "MapboxAPIBaseURL" from NSUserDefaults in `ServiceProvider.createEngine`. - Providing a value in Info.plist is still supported. - Update integration tests to use LocalhostMockServiceProvider - This fixes a bug in the Demo app where you building and running the app or tests could use the wrong baseApiURL based on the current value in user defaults. - Update and correct tests for iOS 17 using all mocked data for unit and UI tests. - Rename `SearchEngine.reverseGeocoding` function to `SearchEngine.reverse`. ### Checklist - [x] Update `CHANGELOG` ### Screenshots | Before | After | | -- | -- | | Screenshot 2024-02-06 at 17 47 49 | Screenshot 2024-02-06 at 17 28 38 | --- CHANGELOG.md | 4 + MapboxSearch.xcodeproj/project.pbxproj | 58 ++- Sources/Demo/AppDelegate.swift | 1 - .../PublicAPI/Engine/SearchEngine.swift | 2 +- .../PublicAPI/ServiceProvider.swift | 21 +- .../MapboxSearchController.swift | 2 +- Tests/CI-dev.xctestplan | 3 - Tests/Demo.xctestplan | 7 +- .../AddressAutofillIntegrationTests.swift | 21 +- ...CategorySearchEngineIntegrationTests.swift | 22 +- .../LocalhostMockServiceProvider.swift | 47 ++ ...ft => MockServerIntegrationTestCase.swift} | 4 +- .../OfflineIntegrationTests.swift | 2 +- .../PlaceAutocompleteIntegrationTests.swift | 22 +- ...earchEngineGeocodingIntegrationTests.swift | 54 +++ .../SearchEngineIntegrationTests.swift | 73 +-- .../Legacy/SearchEngineTests.swift | 6 +- Tests/MapboxSearchUITests/BaseTestCase.swift | 2 + ...tegorySuggestionsIntegrationTestCase.swift | 2 +- ...estionsNavigationIntegrationTestCase.swift | 3 +- .../FavoritesIntegrationTestCase.swift | 41 +- .../FeedbackIntegrationTestCase.swift | 4 +- .../SearchIntegrationTestCase.swift | 18 +- ...tCase.swift => MockServerUITestCase.swift} | 2 +- .../MockWebServer/MockResponse.swift | 55 +-- .../MockWebServer/MockWebServer.swift | 87 +++- .../geocoding-reverse-geocoding.json | 437 ++++++++++++++++++ .../mapbox.places.san.francisco.json | 76 +++ ...coding.json => reverse-geocoding-sbs.json} | 0 .../VisibilityTestCase.swift | 20 +- 30 files changed, 861 insertions(+), 235 deletions(-) create mode 100644 Tests/MapboxSearchIntegrationTests/LocalhostMockServiceProvider.swift rename Tests/MapboxSearchIntegrationTests/{MockServerTestCase.swift => MockServerIntegrationTestCase.swift} (78%) create mode 100644 Tests/MapboxSearchIntegrationTests/SearchEngineGeocodingIntegrationTests.swift rename Tests/MapboxSearchUITests/{MockServerTestCase.swift => MockServerUITestCase.swift} (88%) create mode 100644 Tests/MapboxSearchUITests/MockWebServer/geocoding-reverse-geocoding.json create mode 100644 Tests/MapboxSearchUITests/MockWebServer/mapbox.places.san.francisco.json rename Tests/MapboxSearchUITests/MockWebServer/{reverse-geocoding.json => reverse-geocoding-sbs.json} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b126b4b7..11ca78106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Guide: https://keepachangelog.com/en/1.0.0/ +- [Unit Tests] Update and correct tests for iOS 17 using all mocked data. +- [UI Tests] Update and correct tests for iOS 17 using all mocked data. +- [Search] Rename `SearchEngine.reverseGeocoding` function to `SearchEngine.reverse`. +- [Core] Stop reading "MapboxAPIBaseURL" from UserDefaults in `ServiceProvider.createEngine`. (Providing a value in Info.plist is still supported). - [Core] Remove Swifter library dependency from MapboxSearch target (only used in Test targets) - [Core] Change AbstractSearchEngine.init `supportSBS: Bool = false` parameter to `apiType: ApiType = .SBS`. This changes the default API engine for discover/category and other API requests to SBS. Add ApiType enum to represent non-Autofill and non-PlaceAutocomplete SearchEngine API types. diff --git a/MapboxSearch.xcodeproj/project.pbxproj b/MapboxSearch.xcodeproj/project.pbxproj index 94f2516c0..9298b0489 100644 --- a/MapboxSearch.xcodeproj/project.pbxproj +++ b/MapboxSearch.xcodeproj/project.pbxproj @@ -7,7 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + 042477C32B7290F900D870D5 /* SearchEngineGeocodingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042477C12B7290E700D870D5 /* SearchEngineGeocodingIntegrationTests.swift */; }; + 042477C52B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */; }; + 042477C62B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */; }; + 042477C72B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */; }; 043A3D4D2B30F38300DB681B /* CoreAddress+AddressComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043A3D4C2B30F38300DB681B /* CoreAddress+AddressComponents.swift */; }; + 04AB0B4B2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */; }; + 04AB0B4C2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */; }; + 04AB0B4D2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */; }; + 04BBC6342B61898F00E24E99 /* LocalhostMockServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04BBC6332B61898F00E24E99 /* LocalhostMockServiceProvider.swift */; }; + 04BBC6372B61ABA500E24E99 /* FeedbackIntegrationTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9BBFBD02604A4A500DE9C98 /* FeedbackIntegrationTestCase.swift */; }; 04C0848D2B4C82F3002F9C69 /* SdkInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C0848C2B4C82F3002F9C69 /* SdkInformation.swift */; }; 04C127552B62F6BC00884325 /* ApiType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C127542B62F6BC00884325 /* ApiType.swift */; }; 04C127582B62FFDB00884325 /* ApiType+Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04C127572B62FFDB00884325 /* ApiType+Core.swift */; }; @@ -100,7 +109,7 @@ E648C0C9264297A10044315F /* libc++.1.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E648C0C8264297730044315F /* libc++.1.tbd */; }; F907440F261B00000091899C /* suggestions-san-francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = F907440E261B00000091899C /* suggestions-san-francisco.json */; }; F9074425261B0DF70091899C /* retrieve-san-francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = F9074424261B0DF70091899C /* retrieve-san-francisco.json */; }; - F907443B261B13F40091899C /* MockServerTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F907443A261B13F40091899C /* MockServerTestCase.swift */; }; + F907443B261B13F40091899C /* MockServerUITestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F907443A261B13F40091899C /* MockServerUITestCase.swift */; }; F9074447261B192D0091899C /* recursion.json in Resources */ = {isa = PBXBuildFile; fileRef = F9074446261B192D0091899C /* recursion.json */; }; F9074458261B68B50091899C /* retrieve-minsk.json in Resources */ = {isa = PBXBuildFile; fileRef = F9074457261B68B50091899C /* retrieve-minsk.json */; }; F914EE5A2743E03B00D4F173 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDD2C32508DFE400DC0A98 /* Array+Extensions.swift */; }; @@ -124,8 +133,8 @@ F931B34B25A32C7500AA1674 /* SearchQuerySuggestionImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F931B34A25A32C7500AA1674 /* SearchQuerySuggestionImpl.swift */; }; F931B35225A32CC400AA1674 /* SearchQuerySuggestion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F931B35125A32CC400AA1674 /* SearchQuerySuggestion.swift */; }; F93DA6FF274E4B86005595B5 /* CoreSearchEngineStatics.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93DA6FE274E4B86005595B5 /* CoreSearchEngineStatics.swift */; }; - F94FFA4726453D410019ED9B /* reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding.json */; }; - F94FFA4826453D410019ED9B /* reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding.json */; }; + F94FFA4726453D410019ED9B /* reverse-geocoding-sbs.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding-sbs.json */; }; + F94FFA4826453D410019ED9B /* reverse-geocoding-sbs.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding-sbs.json */; }; F94FFA4A264547CD0019ED9B /* retrieve-multi.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA49264547CD0019ED9B /* retrieve-multi.json */; }; F94FFA4B264547CD0019ED9B /* retrieve-multi.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA49264547CD0019ED9B /* retrieve-multi.json */; }; F953A49325ECEB60003A3681 /* SearchCategorySuggestion+Samples.swift in Sources */ = {isa = PBXBuildFile; fileRef = F953A49225ECEB60003A3681 /* SearchCategorySuggestion+Samples.swift */; }; @@ -173,9 +182,9 @@ F9C557A62670CB0400BE8B94 /* recursion.json in Resources */ = {isa = PBXBuildFile; fileRef = F9074446261B192D0091899C /* recursion.json */; }; F9C557A72670CB0400BE8B94 /* category-cafe.json in Resources */ = {isa = PBXBuildFile; fileRef = F9B62CC7264BC61600492999 /* category-cafe.json */; }; F9C557A82670CB0400BE8B94 /* retrieve-category.json in Resources */ = {isa = PBXBuildFile; fileRef = F9AB03B1261DB50500EDF1E7 /* retrieve-category.json */; }; - F9C557A92670CB0400BE8B94 /* reverse-geocoding.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding.json */; }; + F9C557A92670CB0400BE8B94 /* reverse-geocoding-sbs.json in Resources */ = {isa = PBXBuildFile; fileRef = F94FFA4626453D410019ED9B /* reverse-geocoding-sbs.json */; }; F9C557AA2670CB0400BE8B94 /* retrieve-san-francisco.json in Resources */ = {isa = PBXBuildFile; fileRef = F9074424261B0DF70091899C /* retrieve-san-francisco.json */; }; - F9C557B22670CB4000BE8B94 /* MockServerTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9ACA60726429EA200F50CD4 /* MockServerTestCase.swift */; }; + F9C557B22670CB4000BE8B94 /* MockServerIntegrationTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9ACA60726429EA200F50CD4 /* MockServerIntegrationTestCase.swift */; }; F9C557B32670CB4000BE8B94 /* CategorySearchEngineIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F99190422645ABE6009927A6 /* CategorySearchEngineIntegrationTests.swift */; }; F9C557B42670CB4000BE8B94 /* SearchEngineIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9ACA6162642C18200F50CD4 /* SearchEngineIntegrationTests.swift */; }; F9C557B62670CC4500BE8B94 /* SearchEngineDelegateStub.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDD38A2508E24900DC0A98 /* SearchEngineDelegateStub.swift */; }; @@ -480,7 +489,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 042477C12B7290E700D870D5 /* SearchEngineGeocodingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchEngineGeocodingIntegrationTests.swift; sourceTree = ""; }; + 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "geocoding-reverse-geocoding.json"; sourceTree = ""; }; 043A3D4C2B30F38300DB681B /* CoreAddress+AddressComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreAddress+AddressComponents.swift"; sourceTree = ""; }; + 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = mapbox.places.san.francisco.json; sourceTree = ""; }; + 04BBC6332B61898F00E24E99 /* LocalhostMockServiceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalhostMockServiceProvider.swift; sourceTree = ""; }; 04C0848C2B4C82F3002F9C69 /* SdkInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SdkInformation.swift; sourceTree = ""; }; 04C127542B62F6BC00884325 /* ApiType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiType.swift; sourceTree = ""; }; 04C127572B62FFDB00884325 /* ApiType+Core.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApiType+Core.swift"; sourceTree = ""; }; @@ -555,7 +568,7 @@ E648C0C8264297730044315F /* libc++.1.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.1.tbd"; path = "usr/lib/libc++.1.tbd"; sourceTree = SDKROOT; }; F907440E261B00000091899C /* suggestions-san-francisco.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "suggestions-san-francisco.json"; sourceTree = ""; }; F9074424261B0DF70091899C /* retrieve-san-francisco.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "retrieve-san-francisco.json"; sourceTree = ""; }; - F907443A261B13F40091899C /* MockServerTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerTestCase.swift; sourceTree = ""; }; + F907443A261B13F40091899C /* MockServerUITestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerUITestCase.swift; sourceTree = ""; }; F9074446261B192D0091899C /* recursion.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recursion.json; sourceTree = ""; }; F9074457261B68B50091899C /* retrieve-minsk.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "retrieve-minsk.json"; sourceTree = ""; }; F914EE632743E4F400D4F173 /* CoreAliases.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreAliases.swift; sourceTree = ""; }; @@ -575,7 +588,7 @@ F931B34A25A32C7500AA1674 /* SearchQuerySuggestionImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchQuerySuggestionImpl.swift; sourceTree = ""; }; F931B35125A32CC400AA1674 /* SearchQuerySuggestion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchQuerySuggestion.swift; sourceTree = ""; }; F93DA6FE274E4B86005595B5 /* CoreSearchEngineStatics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreSearchEngineStatics.swift; sourceTree = ""; }; - F94FFA4626453D410019ED9B /* reverse-geocoding.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "reverse-geocoding.json"; sourceTree = ""; }; + F94FFA4626453D410019ED9B /* reverse-geocoding-sbs.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "reverse-geocoding-sbs.json"; sourceTree = ""; }; F94FFA49264547CD0019ED9B /* retrieve-multi.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "retrieve-multi.json"; sourceTree = ""; }; F953A49225ECEB60003A3681 /* SearchCategorySuggestion+Samples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchCategorySuggestion+Samples.swift"; sourceTree = ""; }; F953A49925ECF3D7003A3681 /* SearchQuerySuggestionImpl+Samples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchQuerySuggestionImpl+Samples.swift"; sourceTree = ""; }; @@ -595,7 +608,7 @@ F9AB03A5261DB37C00EDF1E7 /* suggestions-categories.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "suggestions-categories.json"; sourceTree = ""; }; F9AB03B1261DB50500EDF1E7 /* retrieve-category.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "retrieve-category.json"; sourceTree = ""; }; F9AB03C2261DBD7F00EDF1E7 /* MockResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockResponse.swift; sourceTree = ""; }; - F9ACA60726429EA200F50CD4 /* MockServerTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerTestCase.swift; sourceTree = ""; }; + F9ACA60726429EA200F50CD4 /* MockServerIntegrationTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockServerIntegrationTestCase.swift; sourceTree = ""; }; F9ACA6112642B66600F50CD4 /* MockWebServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockWebServer.swift; sourceTree = ""; }; F9ACA6162642C18200F50CD4 /* SearchEngineIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchEngineIntegrationTests.swift; sourceTree = ""; }; F9B62CC7264BC61600492999 /* category-cafe.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "category-cafe.json"; sourceTree = ""; }; @@ -1356,7 +1369,7 @@ F9AB03C2261DBD7F00EDF1E7 /* MockResponse.swift */, F9ACA6112642B66600F50CD4 /* MockWebServer.swift */, F9074446261B192D0091899C /* recursion.json */, - F94FFA4626453D410019ED9B /* reverse-geocoding.json */, + F94FFA4626453D410019ED9B /* reverse-geocoding-sbs.json */, F9B62CC7264BC61600492999 /* category-cafe.json */, F94FFA49264547CD0019ED9B /* retrieve-multi.json */, F9AB03B1261DB50500EDF1E7 /* retrieve-category.json */, @@ -1366,6 +1379,8 @@ F91D2D0A26174F5B00F7DFDF /* suggestions-minsk.json */, F9B62CCA264BCC2600492999 /* suggestions-empty.json */, F907440E261B00000091899C /* suggestions-san-francisco.json */, + 04AB0B4A2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json */, + 042477C42B72CCB000D870D5 /* geocoding-reverse-geocoding.json */, ); path = MockWebServer; sourceTree = ""; @@ -1461,11 +1476,13 @@ F9C557292670C88E00BE8B94 /* MapboxSearchIntegrationTests */ = { isa = PBXGroup; children = ( + 04BBC6332B61898F00E24E99 /* LocalhostMockServiceProvider.swift */, 2CE1B9F72A13C4E6005B043F /* AddressAutofillIntegrationTests.swift */, 2C10133329F1C6200094413F /* PlaceAutocompleteIntegrationTests.swift */, - F9ACA60726429EA200F50CD4 /* MockServerTestCase.swift */, + F9ACA60726429EA200F50CD4 /* MockServerIntegrationTestCase.swift */, F9274FF3273AA72800708F37 /* OfflineIntegrationTests.swift */, F9ACA6162642C18200F50CD4 /* SearchEngineIntegrationTests.swift */, + 042477C12B7290E700D870D5 /* SearchEngineGeocodingIntegrationTests.swift */, F99190422645ABE6009927A6 /* CategorySearchEngineIntegrationTests.swift */, F9C5572C2670C88E00BE8B94 /* Info.plist */, ); @@ -1780,7 +1797,7 @@ F91D2D162617513700F7DFDF /* MockWebServer */, F983EBDB2550171200CE13CD /* Integration */, FEEDD3C92508E45B00DC0A98 /* XCUIApplication+Extensions.swift */, - F907443A261B13F40091899C /* MockServerTestCase.swift */, + F907443A261B13F40091899C /* MockServerUITestCase.swift */, FEEDD3C82508E45B00DC0A98 /* BaseTestCase.swift */, FEEDD3CC2508E45B00DC0A98 /* VisibilityTestCase.swift */, FEEDD3CD2508E45B00DC0A98 /* Info.plist */, @@ -2042,12 +2059,14 @@ F9ACA61C2642C49900F50CD4 /* suggestions-categories.json in Resources */, F9ACA61E2642C4A000F50CD4 /* suggestions-san-francisco.json in Resources */, F94FFA4A264547CD0019ED9B /* retrieve-multi.json in Resources */, + 042477C62B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, 2CD8AC4429F1D38800C47BE4 /* suggestions-category-with-coordinates.json in Resources */, F9B62CCB264BCC2600492999 /* suggestions-empty.json in Resources */, + 04AB0B4C2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */, F9ACA6182642C48C00F50CD4 /* recursion.json in Resources */, F9B62CC8264BC61600492999 /* category-cafe.json in Resources */, F9ACA6192642C49000F50CD4 /* retrieve-category.json in Resources */, - F94FFA4726453D410019ED9B /* reverse-geocoding.json in Resources */, + F94FFA4726453D410019ED9B /* reverse-geocoding-sbs.json in Resources */, 2CE1B9FE2A13D41A005B043F /* address-retrieve-san-francisco.json in Resources */, 2CD8AC4A29F1D38800C47BE4 /* suggestions-with-mixed-coordinates.json in Resources */, 2CD8AC5329F28D6900C47BE4 /* retrieve-poi.json in Resources */, @@ -2066,13 +2085,15 @@ F9074447261B192D0091899C /* recursion.json in Resources */, F94FFA4B264547CD0019ED9B /* retrieve-multi.json in Resources */, 2CD8AC4529F1D38800C47BE4 /* suggestions-category-with-coordinates.json in Resources */, + 04AB0B4D2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */, F9B62CCC264BCC2600492999 /* suggestions-empty.json in Resources */, F91D2D0B26174F5F00F7DFDF /* suggestions-minsk.json in Resources */, F9B62CC9264BC61600492999 /* category-cafe.json in Resources */, F907440F261B00000091899C /* suggestions-san-francisco.json in Resources */, - F94FFA4826453D410019ED9B /* reverse-geocoding.json in Resources */, + F94FFA4826453D410019ED9B /* reverse-geocoding-sbs.json in Resources */, 2CD8AC4B29F1D38800C47BE4 /* suggestions-with-mixed-coordinates.json in Resources */, 2CD8AC5429F28D6900C47BE4 /* retrieve-poi.json in Resources */, + 042477C72B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, F9074425261B0DF70091899C /* retrieve-san-francisco.json in Resources */, 2CD8AC4829F1D38800C47BE4 /* suggestions-with-coordinates.json in Resources */, ); @@ -2088,12 +2109,14 @@ F9C557A22670CB0400BE8B94 /* suggestions-categories.json in Resources */, F9C557A32670CB0400BE8B94 /* suggestions-san-francisco.json in Resources */, F9C557A42670CB0400BE8B94 /* retrieve-multi.json in Resources */, + 042477C52B72CCB000D870D5 /* geocoding-reverse-geocoding.json in Resources */, 2CD8AC4329F1D38800C47BE4 /* suggestions-category-with-coordinates.json in Resources */, F9C557A52670CB0400BE8B94 /* suggestions-empty.json in Resources */, + 04AB0B4B2B6AADB700FDE7D5 /* mapbox.places.san.francisco.json in Resources */, F9C557A62670CB0400BE8B94 /* recursion.json in Resources */, F9C557A72670CB0400BE8B94 /* category-cafe.json in Resources */, F9C557A82670CB0400BE8B94 /* retrieve-category.json in Resources */, - F9C557A92670CB0400BE8B94 /* reverse-geocoding.json in Resources */, + F9C557A92670CB0400BE8B94 /* reverse-geocoding-sbs.json in Resources */, 2CE1B9FC2A13D412005B043F /* address-retrieve-san-francisco.json in Resources */, 2CD8AC4929F1D38800C47BE4 /* suggestions-with-mixed-coordinates.json in Resources */, 2CD8AC5229F28D6900C47BE4 /* retrieve-poi.json in Resources */, @@ -2583,13 +2606,14 @@ F9201EE0253F1C6F002D141B /* CategorySuggestionsNavigationIntegrationTestCase.swift in Sources */, FEEDD3D12508E45B00DC0A98 /* SearchIntegrationTestCase.swift in Sources */, F9201ECA253EECE0002D141B /* CategorySuggestionsIntegrationTestCase.swift in Sources */, - F907443B261B13F40091899C /* MockServerTestCase.swift in Sources */, + F907443B261B13F40091899C /* MockServerUITestCase.swift in Sources */, F9ACA6132642B66600F50CD4 /* MockWebServer.swift in Sources */, FEEDD3D22508E45B00DC0A98 /* VisibilityTestCase.swift in Sources */, F9AB03C3261DBD7F00EDF1E7 /* MockResponse.swift in Sources */, FEEDD3CE2508E45B00DC0A98 /* BaseTestCase.swift in Sources */, FEEDD3D02508E45B00DC0A98 /* FavoritesIntegrationTestCase.swift in Sources */, FEEDD3CF2508E45B00DC0A98 /* XCUIApplication+Extensions.swift in Sources */, + 04BBC6372B61ABA500E24E99 /* FeedbackIntegrationTestCase.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2605,7 +2629,9 @@ F9C557BF2670CD4300BE8B94 /* CoreRequestOptions+Samples.swift in Sources */, F9C557BB2670CCC000BE8B94 /* SearchResultType+Extensions.swift in Sources */, F9C557BA2670CCAB00BE8B94 /* TestDataProviderRecord.swift in Sources */, + 042477C32B7290F900D870D5 /* SearchEngineGeocodingIntegrationTests.swift in Sources */, F9C557672670CB0400BE8B94 /* MockResponse.swift in Sources */, + 04BBC6342B61898F00E24E99 /* LocalhostMockServiceProvider.swift in Sources */, 2C10133429F1C6200094413F /* PlaceAutocompleteIntegrationTests.swift in Sources */, F9C557682670CB0400BE8B94 /* MockWebServer.swift in Sources */, F9C557BD2670CD0D00BE8B94 /* CoreSuggestAction+Samples.swift in Sources */, @@ -2620,7 +2646,7 @@ F9C557BC2670CCF200BE8B94 /* CLLocationCoordinate2D+Samples.swift in Sources */, 2CE1B9F82A13C4E6005B043F /* AddressAutofillIntegrationTests.swift in Sources */, F9C557B32670CB4000BE8B94 /* CategorySearchEngineIntegrationTests.swift in Sources */, - F9C557B22670CB4000BE8B94 /* MockServerTestCase.swift in Sources */, + F9C557B22670CB4000BE8B94 /* MockServerIntegrationTestCase.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Demo/AppDelegate.swift b/Sources/Demo/AppDelegate.swift index 9adc6a033..15ea8746a 100644 --- a/Sources/Demo/AppDelegate.swift +++ b/Sources/Demo/AppDelegate.swift @@ -12,7 +12,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if ProcessInfo.processInfo.arguments.contains("--uitesting") { ServiceProvider.shared.localFavoritesProvider.deleteAll() ServiceProvider.shared.localHistoryProvider.deleteAll() - UserDefaults.resetStandardUserDefaults() } return true diff --git a/Sources/MapboxSearch/PublicAPI/Engine/SearchEngine.swift b/Sources/MapboxSearch/PublicAPI/Engine/SearchEngine.swift index 81621f736..c6d16e15b 100644 --- a/Sources/MapboxSearch/PublicAPI/Engine/SearchEngine.swift +++ b/Sources/MapboxSearch/PublicAPI/Engine/SearchEngine.swift @@ -450,7 +450,7 @@ extension SearchEngine { /// - Parameters: /// - options: Options with coordinates, mode, limits and query types for reverse geocoding. /// - completion: completion handler with either reverse geocoding Resuts or Error. - public func reverseGeocoding( + public func reverse( options: ReverseGeocodingOptions, completion: @escaping (Result<[SearchResult], SearchError>) -> Void ) { diff --git a/Sources/MapboxSearch/PublicAPI/ServiceProvider.swift b/Sources/MapboxSearch/PublicAPI/ServiceProvider.swift index 3b872ccd2..7de11fe18 100644 --- a/Sources/MapboxSearch/PublicAPI/ServiceProvider.swift +++ b/Sources/MapboxSearch/PublicAPI/ServiceProvider.swift @@ -27,11 +27,21 @@ public typealias FavoritesProvider = LocalDataProvider /// Built-in local data provider for ``HistoryRecord`` data. public typealias HistoryProvider = LocalDataProvider +// MARK: - ServiceProvider + /// Services provider for SearchEngine public class ServiceProvider: ServiceProviderProtocol { - /// Customize API host URL + /// Customize API host URL with a value from the Info.plist + /// Also supports reading a process argument when in non-Release UITest builds public static var customBaseURL: String? { - Bundle.main.object(forInfoDictionaryKey: baseURLPlistKey) as? String +#if !RELEASE + if ProcessInfo.processInfo.arguments.contains(where: { $0 == "--uitesting" }) { + let testingBaseUrl = ProcessInfo.processInfo.environment["search_endpoint"] + return testingBaseUrl + } +#endif + + return Bundle.main.object(forInfoDictionaryKey: baseURLPlistKey) as? String } /// LocalDataProvider for favorites records @@ -60,15 +70,10 @@ extension ServiceProvider: EngineProviderProtocol { accessToken: String, locationProvider: CoreLocationProvider? ) -> CoreSearchEngineProtocol { - // UserDefaults can be used to setup base url in runtime (e.g. UI tests) - // UserDefaults can be used to setup base url in runtime (e.g. UI tests) - let defaultsBaseURL = UserDefaults.standard.value(forKey: baseURLPlistKey) as? String - let bundleBaseURL = Bundle.main.object(forInfoDictionaryKey: baseURLPlistKey) as? String - MapboxOptions.accessToken = accessToken let engineOptions = CoreSearchEngine.Options( - baseUrl: bundleBaseURL ?? defaultsBaseURL, + baseUrl: Self.customBaseURL, apiType: NSNumber(value: apiType.rawValue), sdkInformation: SdkInformation.defaultInfo, eventsUrl: nil diff --git a/Sources/MapboxSearchUI/MapboxSearchController.swift b/Sources/MapboxSearchUI/MapboxSearchController.swift index 100486f92..71660bead 100644 --- a/Sources/MapboxSearchUI/MapboxSearchController.swift +++ b/Sources/MapboxSearchUI/MapboxSearchController.swift @@ -643,7 +643,7 @@ extension MapboxSearchController: SearchCategoriesRootViewDelegate { case .success(let items): self.delegate?.categorySearchResultsReceived(category: category, results: items) case .failure(let searchError): - print("Failed search; error=\(searchError)") + _Logger.searchSDK.error("Failed search; error=\(searchError)") self.presentSearchError(searchError) } self.mapboxPanelController?.setState(.collapsed, animated: true) diff --git a/Tests/CI-dev.xctestplan b/Tests/CI-dev.xctestplan index f57885634..a0fe51451 100644 --- a/Tests/CI-dev.xctestplan +++ b/Tests/CI-dev.xctestplan @@ -32,7 +32,6 @@ "testTargets" : [ { "skippedTests" : [ - "MockServerTestCase", "OfflineIntegrationTests" ], "target" : { @@ -43,7 +42,6 @@ }, { "skippedTests" : [ - "MockServerTestCase" ], "target" : { "containerPath" : "container:MapboxSearch.xcodeproj", @@ -55,7 +53,6 @@ "enabled" : false, "skippedTests" : [ "BaseTestCase", - "MockServerTestCase" ], "target" : { "containerPath" : "container:MapboxSearch.xcodeproj", diff --git a/Tests/Demo.xctestplan b/Tests/Demo.xctestplan index 2693e2a70..7dcacae8b 100644 --- a/Tests/Demo.xctestplan +++ b/Tests/Demo.xctestplan @@ -35,7 +35,7 @@ "testTargets" : [ { "skippedTests" : [ - "MockServerTestCase" + "MockServerIntegrationTestCase" ], "target" : { "containerPath" : "container:MapboxSearch.xcodeproj", @@ -44,9 +44,6 @@ } }, { - "skippedTests" : [ - "MockServerTestCase" - ], "target" : { "containerPath" : "container:MapboxSearch.xcodeproj", "identifier" : "3A0D7E54233522D4006D81BB", @@ -56,7 +53,7 @@ { "skippedTests" : [ "BaseTestCase", - "MockServerTestCase" + "MockServerUITestCase" ], "target" : { "containerPath" : "container:MapboxSearch.xcodeproj", diff --git a/Tests/MapboxSearchIntegrationTests/AddressAutofillIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/AddressAutofillIntegrationTests.swift index 5d8d3cd16..6cc2d6962 100644 --- a/Tests/MapboxSearchIntegrationTests/AddressAutofillIntegrationTests.swift +++ b/Tests/MapboxSearchIntegrationTests/AddressAutofillIntegrationTests.swift @@ -2,15 +2,30 @@ import CoreLocation @testable import MapboxSearch import XCTest -final class AddressAutofillIntegrationTests: MockServerTestCase { +final class AddressAutofillIntegrationTests: MockServerIntegrationTestCase { private var addressAutofill: AddressAutofill! + private let locationProvider = WrapperLocationProvider(wrapping: DefaultLocationProvider()) override func setUp() { super.setUp() - addressAutofill = AddressAutofill( + let reporter = CoreUserActivityReporter.getOrCreate( + for: CoreUserActivityReporterOptions( + sdkInformation: + SdkInformation.defaultInfo, + eventsUrl: nil + ) + ) + + let engine = LocalhostMockServiceProvider.shared.createEngine( + apiType: CoreSearchEngine.ApiType.autofill, accessToken: "access-token", - locationProvider: DefaultLocationProvider() + locationProvider: locationProvider + ) + + addressAutofill = AddressAutofill( + searchEngine: engine, + userActivityReporter: reporter ) } diff --git a/Tests/MapboxSearchIntegrationTests/CategorySearchEngineIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/CategorySearchEngineIntegrationTests.swift index 2b58448e8..841b20f2f 100644 --- a/Tests/MapboxSearchIntegrationTests/CategorySearchEngineIntegrationTests.swift +++ b/Tests/MapboxSearchIntegrationTests/CategorySearchEngineIntegrationTests.swift @@ -2,18 +2,24 @@ import CoreLocation @testable import MapboxSearch import XCTest -class CategorySearchEngineIntegrationTests: MockServerTestCase { - lazy var searchEngine = CategorySearchEngine( - accessToken: "access-token", - locationProvider: DefaultLocationProvider(), - apiType: .SBS - ) +final class CategorySearchEngineIntegrationTests: MockServerIntegrationTestCase { + private var searchEngine: CategorySearchEngine! + + override func setUp() { + super.setUp() + + searchEngine = CategorySearchEngine( + accessToken: "access-token", + serviceProvider: LocalhostMockServiceProvider.shared, + apiType: .SBS + ) + } func testCategorySearch() throws { try server.setResponse(.categoryCafe) let expectation = XCTestExpectation(description: "Expecting results") - searchEngine.search(categoryName: "ATM") { result in + searchEngine.search(categoryName: "cafe") { result in switch result { case .success(let searchResults): XCTAssertFalse(searchResults.isEmpty) @@ -30,7 +36,7 @@ class CategorySearchEngineIntegrationTests: MockServerTestCase { try server.setResponse(.categoryCafe, statusCode: 500) let expectation = XCTestExpectation(description: "Expecting failure") - searchEngine.search(categoryName: "ATM") { result in + searchEngine.search(categoryName: "cafe") { result in switch result { case .success: XCTFail("Not expected") diff --git a/Tests/MapboxSearchIntegrationTests/LocalhostMockServiceProvider.swift b/Tests/MapboxSearchIntegrationTests/LocalhostMockServiceProvider.swift new file mode 100644 index 000000000..89ec1513d --- /dev/null +++ b/Tests/MapboxSearchIntegrationTests/LocalhostMockServiceProvider.swift @@ -0,0 +1,47 @@ +@testable import MapboxSearch +import XCTest + +class LocalhostMockServiceProvider: ServiceProviderProtocol { + public static var customBaseURL: String? + + /// LocalDataProvider for favorites records + public let localFavoritesProvider = FavoritesProvider() + /// LocalDataProvider for history records + public let localHistoryProvider = HistoryProvider() + /// MapboxMobileEvents manager for analytics usage + public let eventsManager = EventsManager() + + /// Responsible for sending feedback related events. + public private(set) lazy var feedbackManager = FeedbackManager(eventsManager: eventsManager) + + /// Shared instance of ServiceProvider + public static let shared = LocalhostMockServiceProvider() + + var dataLayerProviders: [IndexableDataProvider] { [localHistoryProvider, localFavoritesProvider] } +} + +extension LocalhostMockServiceProvider: EngineProviderProtocol { + func getStoredAccessToken() -> String? { + Bundle.main.object(forInfoDictionaryKey: accessTokenPlistKey) as? String + } + + func createEngine( + apiType: CoreSearchEngine.ApiType, + accessToken: String, + locationProvider: CoreLocationProvider? + ) -> CoreSearchEngineProtocol { + MapboxOptions.accessToken = accessToken + + let engineOptions = CoreSearchEngine.Options( + baseUrl: Self.customBaseURL, + apiType: NSNumber(value: apiType.rawValue), + sdkInformation: SdkInformation.defaultInfo, + eventsUrl: nil + ) + + return CoreSearchEngine( + options: engineOptions, + location: locationProvider + ) + } +} diff --git a/Tests/MapboxSearchIntegrationTests/MockServerTestCase.swift b/Tests/MapboxSearchIntegrationTests/MockServerIntegrationTestCase.swift similarity index 78% rename from Tests/MapboxSearchIntegrationTests/MockServerTestCase.swift rename to Tests/MapboxSearchIntegrationTests/MockServerIntegrationTestCase.swift index 86103e3d9..b75bfe048 100644 --- a/Tests/MapboxSearchIntegrationTests/MockServerTestCase.swift +++ b/Tests/MapboxSearchIntegrationTests/MockServerIntegrationTestCase.swift @@ -2,7 +2,7 @@ import CoreLocation @testable import MapboxSearch import XCTest -class MockServerTestCase: XCTestCase { +class MockServerIntegrationTestCase: XCTestCase { let server = MockWebServer() func setServerResponse(_ response: MockResponse, query: String? = nil) throws { @@ -12,7 +12,7 @@ class MockServerTestCase: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() - UserDefaults.standard.setValue(server.endpoint, forKey: "MapboxAPIBaseURL") + LocalhostMockServiceProvider.customBaseURL = server.endpoint try server.start() } diff --git a/Tests/MapboxSearchIntegrationTests/OfflineIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/OfflineIntegrationTests.swift index 548703d3d..c8cdb2580 100644 --- a/Tests/MapboxSearchIntegrationTests/OfflineIntegrationTests.swift +++ b/Tests/MapboxSearchIntegrationTests/OfflineIntegrationTests.swift @@ -6,7 +6,7 @@ import MapboxCommon @testable import MapboxSearch import XCTest -class OfflineIntegrationTests: MockServerTestCase { +class OfflineIntegrationTests: MockServerIntegrationTestCase { let delegate = SearchEngineDelegateStub() let searchEngine = SearchEngine() diff --git a/Tests/MapboxSearchIntegrationTests/PlaceAutocompleteIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/PlaceAutocompleteIntegrationTests.swift index 9a5f94359..8c2ae9b0a 100644 --- a/Tests/MapboxSearchIntegrationTests/PlaceAutocompleteIntegrationTests.swift +++ b/Tests/MapboxSearchIntegrationTests/PlaceAutocompleteIntegrationTests.swift @@ -2,15 +2,29 @@ import CoreLocation @testable import MapboxSearch import XCTest -final class PlaceAutocompleteIntegrationTests: MockServerTestCase { +final class PlaceAutocompleteIntegrationTests: MockServerIntegrationTestCase { private var placeAutocomplete: PlaceAutocomplete! override func setUp() { super.setUp() - placeAutocomplete = PlaceAutocomplete( + let reporter = CoreUserActivityReporter.getOrCreate( + for: CoreUserActivityReporterOptions( + sdkInformation: + SdkInformation.defaultInfo, + eventsUrl: nil + ) + ) + + let engine = LocalhostMockServiceProvider.shared.createEngine( + apiType: CoreSearchEngine.ApiType.SBS, accessToken: "access-token", - locationProvider: DefaultLocationProvider() + locationProvider: WrapperLocationProvider(wrapping: DefaultLocationProvider()) + ) + + placeAutocomplete = PlaceAutocomplete( + searchEngine: engine, + userActivityReporter: reporter ) } @@ -21,7 +35,7 @@ final class PlaceAutocompleteIntegrationTests: MockServerTestCase { try server.setResponse(.retrieveSanFrancisco) var suggestion: PlaceAutocomplete.Suggestion? - placeAutocomplete.suggestions(for: "query") { result in + placeAutocomplete.suggestions(for: "San Francisco") { result in switch result { case .success(let suggestions): XCTAssertEqual(suggestions.count, 10) diff --git a/Tests/MapboxSearchIntegrationTests/SearchEngineGeocodingIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/SearchEngineGeocodingIntegrationTests.swift new file mode 100644 index 000000000..6c5cbda1c --- /dev/null +++ b/Tests/MapboxSearchIntegrationTests/SearchEngineGeocodingIntegrationTests.swift @@ -0,0 +1,54 @@ +import CoreLocation +@testable import MapboxSearch +import XCTest + +class SearchEngineGeocodingIntegrationTests: MockServerIntegrationTestCase { + let delegate = SearchEngineDelegateStub() + var searchEngine: SearchEngine! + + override func setUp() { + super.setUp() + + searchEngine = SearchEngine( + accessToken: "access-token", + serviceProvider: LocalhostMockServiceProvider.shared, + locationProvider: DefaultLocationProvider(), + apiType: .geocoding + ) + + searchEngine.delegate = delegate + } + + func testReverseGeocodingSearch() throws { + try server.setResponse(.reverseGeocoding) + + let expectation = XCTestExpectation() + let options = ReverseGeocodingOptions(point: CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0)) + + // Search engine is a SBS type! + searchEngine.reverse(options: options) { result in + if case .success(let reverseGeocodingResults) = result { + XCTAssertFalse(reverseGeocodingResults.isEmpty) + } else { + XCTFail("No resolved result") + } + expectation.fulfill() + } + + wait(for: [expectation], timeout: 10) + } + + func testReverseGeocodingSearchFailed() throws { + try server.setResponse(.reverseGeocoding, statusCode: 500) + + let expectation = XCTestExpectation() + let options = ReverseGeocodingOptions(point: CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0)) + searchEngine.reverse(options: options) { result in + if case .failure(.reverseGeocodingFailed(let reasonError as NSError, _)) = result { + XCTAssert(reasonError.code == 500) + expectation.fulfill() + } + } + wait(for: [expectation], timeout: 10) + } +} diff --git a/Tests/MapboxSearchIntegrationTests/SearchEngineIntegrationTests.swift b/Tests/MapboxSearchIntegrationTests/SearchEngineIntegrationTests.swift index b52ea86d1..3fb4112f2 100644 --- a/Tests/MapboxSearchIntegrationTests/SearchEngineIntegrationTests.swift +++ b/Tests/MapboxSearchIntegrationTests/SearchEngineIntegrationTests.swift @@ -2,16 +2,19 @@ import CoreLocation @testable import MapboxSearch import XCTest -class SearchEngineIntegrationTests: MockServerTestCase { +class SearchEngineIntegrationTests: MockServerIntegrationTestCase { let delegate = SearchEngineDelegateStub() - lazy var searchEngine = SearchEngine( - accessToken: "access-token", - locationProvider: DefaultLocationProvider(), - apiType: .SBS - ) + var searchEngine: SearchEngine! - override func setUpWithError() throws { - try super.setUpWithError() + override func setUp() { + super.setUp() + + searchEngine = SearchEngine( + accessToken: "access-token", + serviceProvider: LocalhostMockServiceProvider.shared, + locationProvider: DefaultLocationProvider(), + apiType: .SBS + ) searchEngine.delegate = delegate } @@ -27,7 +30,7 @@ class SearchEngineIntegrationTests: MockServerTestCase { } func testSearchBrokenResponse() throws { - server.setResponse(endpoint: .suggest, body: "This is so sad!", statusCode: 200) + server.setResponse(endpoint: .suggestEmpty, body: "This is so sad!", statusCode: 200) let expectation = delegate.errorExpectation searchEngine.search(query: "some query") wait(for: [expectation], timeout: 10) @@ -73,55 +76,17 @@ class SearchEngineIntegrationTests: MockServerTestCase { XCTAssertNil(delegate.error) } - func testReverseGeocodingSearch() throws { - try server.setResponse(.reverseGeocoding) - - let expectation = XCTestExpectation() - let options = ReverseGeocodingOptions(point: CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0)) - - searchEngine.reverseGeocoding(options: options) { result in - if case .success(let reverseGeocodingResults) = result { - XCTAssertFalse(reverseGeocodingResults.isEmpty) - } else { - XCTFail("No resolved result") - } - expectation.fulfill() - } - - wait(for: [expectation], timeout: 10) - } - - func testReverseGeocodingSearchFailed() throws { - try server.setResponse(.reverseGeocoding, statusCode: 500) - - let expectation = XCTestExpectation() - let options = ReverseGeocodingOptions(point: CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0)) - searchEngine.reverseGeocoding(options: options) { result in - if case .failure(let error) = result { - if case .reverseGeocodingFailed(let reasonError as NSError, _) = error { - XCTAssert(reasonError.code == 500) - } else { - XCTFail("Not expected") - } - } else { - XCTFail("Not expected") - } - expectation.fulfill() - } - wait(for: [expectation], timeout: 10) - } - func testResolvedSearchResult() throws { try server.setResponse(.suggestMinsk) try server.setResponse(.retrieveMinsk) let updateExpectation = delegate.updateExpectation - searchEngine.search(query: "sample-1") + searchEngine.search(query: "Minsk") wait(for: [updateExpectation], timeout: 10) XCTAssertFalse(searchEngine.suggestions.isEmpty) let successExpectation = delegate.successExpectation - let selectedResult = searchEngine.suggestions.first! + let selectedResult = try XCTUnwrap(searchEngine.suggestions.first) searchEngine.select(suggestion: selectedResult) wait(for: [successExpectation], timeout: 10) @@ -134,15 +99,15 @@ class SearchEngineIntegrationTests: MockServerTestCase { try server.setResponse(.suggestMinsk) try server.setResponse(.retrieveMinsk) - searchEngine.search(query: "Mapbox") + searchEngine.search(query: "Minsk") let updateExpectation = delegate.updateExpectation wait(for: [updateExpectation], timeout: 10) XCTAssertFalse(searchEngine.suggestions.isEmpty) - let selectedResult = searchEngine.suggestions.first! + let selectedResult = try XCTUnwrap(searchEngine.suggestions.first) - searchEngine.search(query: "Mapbo") + searchEngine.search(query: "Min") searchEngine.select(suggestion: selectedResult) let successExpectation = delegate.successExpectation @@ -157,12 +122,12 @@ class SearchEngineIntegrationTests: MockServerTestCase { try server.setResponse(.retrieveMinsk, statusCode: 500) let updateExpectation = delegate.updateExpectation - searchEngine.search(query: "sample-1") + searchEngine.search(query: "Minsk") wait(for: [updateExpectation], timeout: 10) XCTAssertFalse(searchEngine.suggestions.isEmpty) let errorExpectation = delegate.errorExpectation - let selectedResult = searchEngine.suggestions.first! + let selectedResult = try XCTUnwrap(searchEngine.suggestions.first) searchEngine.select(suggestion: selectedResult) wait(for: [errorExpectation], timeout: 10) diff --git a/Tests/MapboxSearchTests/Legacy/SearchEngineTests.swift b/Tests/MapboxSearchTests/Legacy/SearchEngineTests.swift index 23c468462..83d5cfdc2 100644 --- a/Tests/MapboxSearchTests/Legacy/SearchEngineTests.swift +++ b/Tests/MapboxSearchTests/Legacy/SearchEngineTests.swift @@ -72,7 +72,7 @@ class SearchEngineTests: XCTestCase { engine.searchResponse = coreResponse let expectation = XCTestExpectation() let point = CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0) - searchEngine.reverseGeocoding(options: .init(point: point)) { result in + searchEngine.reverse(options: .init(point: point)) { result in if case .success(let reverseGeocodingResults) = result { XCTAssertEqual(results.map(\.id), reverseGeocodingResults.map(\.id)) } else { @@ -396,7 +396,7 @@ class SearchEngineTests: XCTestCase { let expectation = XCTestExpectation() var error: SearchError? let point = CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0) - searchEngine.reverseGeocoding(options: .init(point: point)) { result in + searchEngine.reverse(options: .init(point: point)) { result in if case .failure(let searchError) = result { error = searchError } else { @@ -429,7 +429,7 @@ class SearchEngineTests: XCTestCase { let expectation = XCTestExpectation() var error: SearchError? let point = CLLocationCoordinate2D(latitude: 12.0, longitude: 12.0) - searchEngine.reverseGeocoding(options: .init(point: point)) { result in + searchEngine.reverse(options: .init(point: point)) { result in if case .failure(let searchError) = result { error = searchError } else { diff --git a/Tests/MapboxSearchUITests/BaseTestCase.swift b/Tests/MapboxSearchUITests/BaseTestCase.swift index 7ab2a9012..ff38336d7 100644 --- a/Tests/MapboxSearchUITests/BaseTestCase.swift +++ b/Tests/MapboxSearchUITests/BaseTestCase.swift @@ -6,6 +6,8 @@ class BaseTestCase: XCTestCase { var app: XCUIApplication! override func setUpWithError() throws { + try super.setUpWithError() + continueAfterFailure = false app = XCUIApplication() app.launchArguments.append("--uitesting") diff --git a/Tests/MapboxSearchUITests/Integration/CategorySuggestionsIntegrationTestCase.swift b/Tests/MapboxSearchUITests/Integration/CategorySuggestionsIntegrationTestCase.swift index 5a7e7f453..51b6b7feb 100644 --- a/Tests/MapboxSearchUITests/Integration/CategorySuggestionsIntegrationTestCase.swift +++ b/Tests/MapboxSearchUITests/Integration/CategorySuggestionsIntegrationTestCase.swift @@ -1,7 +1,7 @@ import XCTest -class CategorySuggestionsIntegrationTestCase: MockServerTestCase { +class CategorySuggestionsIntegrationTestCase: MockServerUITestCase { override func setUpWithError() throws { try super.setUpWithError() app.launch() diff --git a/Tests/MapboxSearchUITests/Integration/CategorySuggestionsNavigationIntegrationTestCase.swift b/Tests/MapboxSearchUITests/Integration/CategorySuggestionsNavigationIntegrationTestCase.swift index 4a758371e..3b29734ee 100644 --- a/Tests/MapboxSearchUITests/Integration/CategorySuggestionsNavigationIntegrationTestCase.swift +++ b/Tests/MapboxSearchUITests/Integration/CategorySuggestionsNavigationIntegrationTestCase.swift @@ -1,7 +1,6 @@ - import XCTest -class CategorySuggestionsNavigationIntegrationTestCase: MockServerTestCase { +class CategorySuggestionsNavigationIntegrationTestCase: MockServerUITestCase { override func setUpWithError() throws { try super.setUpWithError() app.launch() diff --git a/Tests/MapboxSearchUITests/Integration/FavoritesIntegrationTestCase.swift b/Tests/MapboxSearchUITests/Integration/FavoritesIntegrationTestCase.swift index 125336c9b..32def32d3 100644 --- a/Tests/MapboxSearchUITests/Integration/FavoritesIntegrationTestCase.swift +++ b/Tests/MapboxSearchUITests/Integration/FavoritesIntegrationTestCase.swift @@ -1,6 +1,6 @@ import XCTest -class FavoritesIntegrationTestCase: MockServerTestCase { +class FavoritesIntegrationTestCase: MockServerUITestCase { func testAddRemoveFavorite() throws { try server.setResponse(.suggestMinsk) try server.setResponse(.retrieveMinsk) @@ -27,7 +27,7 @@ class FavoritesIntegrationTestCase: MockServerTestCase { favoritesTableView.cells["Minsk"].firstMatch.waitForExistence(timeout: BaseTestCase.defaultTimeout), "Selected favorite item not in favorites list" ) - removeFavorite(element: favoritesTableView.cells["Minsk"].firstMatch) + deleteFavorite(element: favoritesTableView.cells["Minsk"].firstMatch) } func testAddRenameRemoveFavorite() throws { @@ -74,7 +74,7 @@ class FavoritesIntegrationTestCase: MockServerTestCase { favoritesTableView.cells["Riga"].waitForExistence(timeout: BaseTestCase.defaultTimeout), "No renamed favorite in list" ) - removeFavorite(element: favoritesTableView.cells["Riga"].firstMatch) + deleteFavorite(element: favoritesTableView.cells["Riga"].firstMatch) } func testAddRenameCancelRemoveFavorite() throws { @@ -120,7 +120,7 @@ class FavoritesIntegrationTestCase: MockServerTestCase { favoritesTableView.cells["Minsk"].waitForExistence(timeout: BaseTestCase.defaultTimeout), "Original favorite not in list" ) - removeFavorite(element: favoritesTableView.cells["Minsk"].firstMatch) + deleteFavorite(element: favoritesTableView.cells["Minsk"].firstMatch) } func testAddEditLocationRemoveFavorite() throws { @@ -182,7 +182,7 @@ class FavoritesIntegrationTestCase: MockServerTestCase { let newAddress = favoritesTableView.cells[favoriteName].firstMatch.staticTexts["address"].title XCTAssertEqual(addressToChange, newAddress, "New address doesn't applied") - removeFavorite(element: favoritesTableView.cells[favoriteName].firstMatch) + deleteFavorite(element: favoritesTableView.cells[favoriteName].firstMatch) } func testAddRemoveWorkAddress() throws { @@ -205,7 +205,7 @@ class FavoritesIntegrationTestCase: MockServerTestCase { .waitForExistence(timeout: BaseTestCase.defaultTimeout), "Work favorites no moreButton" ) - removeFavorite(element: favoritesTableView.cells["Work"].firstMatch) + removeDefaultFavorite(element: favoritesTableView.cells["Work"].firstMatch) } func testAddRemoveHomeAddress() throws { @@ -228,16 +228,27 @@ class FavoritesIntegrationTestCase: MockServerTestCase { .waitForExistence(timeout: BaseTestCase.defaultTimeout), "Home favorites no moreButton" ) - removeFavorite(element: favoritesTableView.cells["Home"].firstMatch) + removeDefaultFavorite(element: favoritesTableView.cells["Home"].firstMatch) } } extension FavoritesIntegrationTestCase { - func removeFavorite(element: XCUIElement) { + func removeDefaultFavorite(element: XCUIElement) { element.buttons["moreButton"].tap() - // No legal way to set accessibilityIdentifier for UIAlertAction - // Remove location expected to be 3rd - let removeLocation = app.sheets.buttons.element(boundBy: 2) + let removeLocation = app.buttons["Remove location"] + XCTAssertTrue( + removeLocation.waitForExistence(timeout: BaseTestCase.defaultTimeout), + "No remove location action" + ) + removeLocation.tap() + sleep(1) + XCTAssertFalse(element.buttons["moreButton"].exists) + } + + /// Default favorites include Home and Work + func deleteFavorite(element: XCUIElement) { + element.buttons["moreButton"].tap() + let removeLocation = app.buttons["Delete"] XCTAssertTrue( removeLocation.waitForExistence(timeout: BaseTestCase.defaultTimeout), "No remove location action" @@ -249,18 +260,14 @@ extension FavoritesIntegrationTestCase { func editFavoriteLocation(element: XCUIElement) { element.buttons["moreButton"].tap() - // No legal way to set accessibilityIdentifier for UIAlertAction - // Edit location expected to be 2rd - let editLocation = app.sheets.buttons.element(boundBy: 1) + let editLocation = app.buttons["Edit location"] XCTAssertTrue(editLocation.waitForExistence(timeout: BaseTestCase.defaultTimeout), "No edit location action") editLocation.tap() } func renameFavorite(element: XCUIElement) { element.buttons["moreButton"].tap() - // No legal way to set accessibilityIdentifier for UIAlertAction - // Rename expected to be 1st - let editLocation = app.sheets.buttons.element(boundBy: 0) + let editLocation = app.buttons["Rename"] XCTAssertTrue(editLocation.waitForExistence(timeout: BaseTestCase.defaultTimeout), "No edit location action") editLocation.tap() } diff --git a/Tests/MapboxSearchUITests/Integration/FeedbackIntegrationTestCase.swift b/Tests/MapboxSearchUITests/Integration/FeedbackIntegrationTestCase.swift index eef7d2d18..3ef0bfc73 100644 --- a/Tests/MapboxSearchUITests/Integration/FeedbackIntegrationTestCase.swift +++ b/Tests/MapboxSearchUITests/Integration/FeedbackIntegrationTestCase.swift @@ -2,7 +2,7 @@ import XCTest // TODO: Analytics -class FeedbackIntegrationTestCase: MockServerTestCase { +class FeedbackIntegrationTestCase: MockServerUITestCase { override func setUpWithError() throws { try super.setUpWithError() @@ -51,8 +51,6 @@ class FeedbackIntegrationTestCase: MockServerTestCase { let searchResult = app.mapboxSearchController.searchResultTableView waitForHittable(searchResult, message: "SearchResultTableView not hittable") - searchBar.swipeDown() - let recentSearchTable = app.searchResultTableView let recentSearchCell = recentSearchTable.cells.firstMatch XCTAssertTrue( diff --git a/Tests/MapboxSearchUITests/Integration/SearchIntegrationTestCase.swift b/Tests/MapboxSearchUITests/Integration/SearchIntegrationTestCase.swift index 5983a464d..e1c9f1593 100644 --- a/Tests/MapboxSearchUITests/Integration/SearchIntegrationTestCase.swift +++ b/Tests/MapboxSearchUITests/Integration/SearchIntegrationTestCase.swift @@ -1,6 +1,6 @@ import XCTest -class SearchIntegrationTestCase: MockServerTestCase { +class SearchIntegrationTestCase: MockServerUITestCase { func testRecentSearchRemove() throws { try server.setResponse(.suggestSanFrancisco) try server.setResponse(.retrieveSanFrancisco) @@ -30,6 +30,7 @@ class SearchIntegrationTestCase: MockServerTestCase { func testSearchCancel() throws { try server.setResponse(.suggestSanFrancisco) + try server.setResponse(.retrieveSanFrancisco) app.launch() let searchBar = app.searchBar @@ -41,19 +42,4 @@ class SearchIntegrationTestCase: MockServerTestCase { waitForHittable(searchBar.buttons["CancelButton"]).tap() XCTAssertFalse(searchResult.exists, "SearchResultTableView Shouldn't exists") } - - func testRecursionSearch() throws { - try server.setResponse(.recursion) - - app.launch() - let searchBar = app.searchBar - - waitForHittable(searchBar).tap() - searchBar.typeText("Recursion") - - let searchResult = waitForHittable(app.mapboxSearchController.searchResultTableView) - waitForHittable(searchResult.cells["Did you mean recursion?"].firstMatch).tap() - waitForHittable(searchResult.cells["Did you mean recursion?"].firstMatch).tap() - waitForHittable(searchResult.cells["Did you mean recursion?"].firstMatch).tap() - } } diff --git a/Tests/MapboxSearchUITests/MockServerTestCase.swift b/Tests/MapboxSearchUITests/MockServerUITestCase.swift similarity index 88% rename from Tests/MapboxSearchUITests/MockServerTestCase.swift rename to Tests/MapboxSearchUITests/MockServerUITestCase.swift index d36aef5a9..4950a9ee8 100644 --- a/Tests/MapboxSearchUITests/MockServerTestCase.swift +++ b/Tests/MapboxSearchUITests/MockServerUITestCase.swift @@ -1,6 +1,6 @@ import Foundation -class MockServerTestCase: BaseTestCase { +class MockServerUITestCase: BaseTestCase { let server = MockWebServer() override func setUpWithError() throws { diff --git a/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift b/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift index 3c8baf256..613d561fd 100644 --- a/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift +++ b/Tests/MapboxSearchUITests/MockWebServer/MockResponse.swift @@ -1,16 +1,6 @@ import Foundation enum MockResponse { - enum Endpoint: String { - case suggest - case retrieve - case reverse - case multiRetrieve = "retrieve/multi" - case category - case addressSuggest = "autofill/suggest" - case addressRetrieve = "autofill/retrieve" - } - case suggestEmpty case suggestMinsk case suggestSanFrancisco @@ -28,10 +18,12 @@ enum MockResponse { case retrieveAddressSanFrancisco case recursion + case forwardGeocoding case reverseGeocoding + case reverseGeocodingSBS case categoryCafe - var path: String { + var filepath: String { let bundle = Bundle(for: MockWebServer.self) switch self { case .suggestEmpty: @@ -58,8 +50,12 @@ enum MockResponse { return bundle.path(forResource: "retrieve-poi", ofType: "json")! case .recursion: return bundle.path(forResource: "recursion", ofType: "json")! + case .reverseGeocodingSBS: + return bundle.path(forResource: "reverse-geocoding-sbs", ofType: "json")! case .reverseGeocoding: - return bundle.path(forResource: "reverse-geocoding", ofType: "json")! + return bundle.path(forResource: "geocoding-reverse-geocoding", ofType: "json")! + case .forwardGeocoding: + return bundle.path(forResource: "mapbox.places.san.francisco", ofType: "json")! case .multiRetrieve: return bundle.path(forResource: "retrieve-multi", ofType: "json")! case .categoryCafe: @@ -70,39 +66,4 @@ enum MockResponse { return bundle.path(forResource: "address-retrieve-san-francisco", ofType: "json")! } } - - var endpoint: Endpoint { - switch self { - case .suggestAddressSanFrancisco: - return .addressSuggest - - case .retrieveAddressSanFrancisco: - return .addressRetrieve - - case .suggestMinsk, - .suggestEmpty, - .suggestSanFrancisco, - .suggestCategories, - .suggestWithCoordinates, - .suggestWithMixedCoordinates, - .suggestCategoryWithCoordinates, - .recursion: - return .suggest - - case .retrieveSanFrancisco, - .retrieveCategory, - .retrieveMinsk, - .retrievePoi: - return .retrieve - - case .reverseGeocoding: - return .reverse - - case .multiRetrieve: - return .multiRetrieve - - case .categoryCafe: - return .category - } - } } diff --git a/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift b/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift index 75f304e8b..c2ea48815 100644 --- a/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift +++ b/Tests/MapboxSearchUITests/MockWebServer/MockWebServer.swift @@ -7,12 +7,12 @@ final class MockWebServer { private let server = HttpServer() func setResponse(_ response: MockResponse, query: String? = nil, statusCode: Int = 200) throws { - let route = Self.path(for: response.endpoint) - let method = Self.httpMethod(for: response.endpoint) + let route = Self.path(for: response) + let method = Self.httpMethod(for: response) let response = HttpResponse.raw(statusCode, "mocked response", nil) { writer in try writer.write( - Data(contentsOf: URL(fileURLWithPath: response.path)) + Data(contentsOf: URL(fileURLWithPath: response.filepath)) ) } @@ -25,7 +25,7 @@ final class MockWebServer { } } - func setResponse(endpoint: MockResponse.Endpoint, query: String? = nil, body: String, statusCode: Int) { + func setResponse(endpoint: MockResponse, query: String? = nil, body: String, statusCode: Int) { let route = Self.path(for: endpoint) let method = Self.httpMethod(for: endpoint) @@ -58,40 +58,77 @@ extension MockWebServer { case get, post } - fileprivate static func httpMethod(for endpoint: MockResponse.Endpoint) -> HTTPMethod { - switch endpoint { - case .suggest, .category, .reverse, .addressSuggest, .addressRetrieve: + fileprivate static func httpMethod(for response: MockResponse) -> HTTPMethod { + switch response { + case .suggestAddressSanFrancisco, + .retrieveAddressSanFrancisco, + .forwardGeocoding, + .suggestMinsk, + .suggestSanFrancisco, + .suggestEmpty, + .suggestCategories, + .suggestWithCoordinates, + .suggestWithMixedCoordinates, + .suggestCategoryWithCoordinates, + .recursion, + .reverseGeocoding, + .reverseGeocodingSBS, + .categoryCafe: return .get - case .retrieve, .multiRetrieve: + case .multiRetrieve, + .retrieveSanFrancisco, + .retrieveCategory, + .retrieveMinsk, + .retrievePoi: return .post } } - fileprivate static func path(for endpoint: MockResponse.Endpoint) -> String { - var path = "/search/v1/\(endpoint.rawValue)" + fileprivate static func path(for response: MockResponse) -> String { + var path = "/search/v1" - switch endpoint { - case .suggest: - path += "/:query" + switch response { + case .suggestAddressSanFrancisco: + path = "/autofill/v1/suggest/:query" - case .category: - path += "/:category" + case .retrieveAddressSanFrancisco: + path = "/autofill/v1/retrieve/:action.id" - case .multiRetrieve: - break + case .forwardGeocoding: + path = "/geocoding/v5/mapbox.places/:query" - case .reverse: - path += "/:coordinates" + case .suggestMinsk: + path += "/suggest/Minsk" - case .retrieve: - break + case .suggestSanFrancisco: + path += "/suggest/San Francisco" - case .addressSuggest: - path = "/autofill/v1/suggest/:query" + case .suggestEmpty, + .suggestCategories, + .suggestWithCoordinates, + .suggestWithMixedCoordinates, + .suggestCategoryWithCoordinates, + .recursion: + path += "/suggest/:query" - case .addressRetrieve: - path = "/autofill/v1/retrieve/:action.id" + case .retrieveSanFrancisco, + .retrieveCategory, + .retrieveMinsk, + .retrievePoi: + path += "/retrieve" + + case .reverseGeocoding: + path = "geocoding/v5/mapbox.places/:location" + + case .reverseGeocodingSBS: + path += "/:coordinates" + + case .multiRetrieve: + path += "/retrieve/multi" + + case .categoryCafe: + path += "/category/:category" } return path diff --git a/Tests/MapboxSearchUITests/MockWebServer/geocoding-reverse-geocoding.json b/Tests/MapboxSearchUITests/MockWebServer/geocoding-reverse-geocoding.json new file mode 100644 index 000000000..2bbcf3eba --- /dev/null +++ b/Tests/MapboxSearchUITests/MockWebServer/geocoding-reverse-geocoding.json @@ -0,0 +1,437 @@ +{ + "type": "FeatureCollection", + "query": [ + -73.989, + 40.733 + ], + "features": [ + { + "id": "address.5006143367295016", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + "accuracy": "rooftop", + "mapbox_id": "dXJuOm1ieGFkcjo4NTA4ODFhOS1lZjY1LTRkMTUtOWQyYS1kNmY0MTllZmJlMDI" + }, + "text": "East 13th Street", + "place_name": "120 East 13th Street, New York, New York 10003, United States", + "center": [ + -73.9889528, + 40.7329202 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -73.9889528, + 40.7329202 + ] + }, + "address": "120", + "context": [ + { + "id": "neighborhood.187075820", + "mapbox_id": "dXJuOm1ieHBsYzpDeWFNN0E", + "wikidata": "Q1043326", + "text": "East Village" + }, + { + "id": "postcode.5006143367295016", + "text": "10003" + }, + { + "id": "locality.338856684", + "mapbox_id": "dXJuOm1ieHBsYzpGREtLN0E", + "wikidata": "Q11299", + "text": "Manhattan" + }, + { + "id": "place.233720044", + "mapbox_id": "dXJuOm1ieHBsYzpEZTVJN0E", + "wikidata": "Q60", + "text": "New York" + }, + { + "id": "district.17000172", + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416", + "text": "New York County" + }, + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "neighborhood.187075820", + "type": "Feature", + "place_type": [ + "neighborhood" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpDeWFNN0E", + "wikidata": "Q1043326" + }, + "text": "East Village", + "place_name": "East Village, New York, New York, United States", + "bbox": [ + -73.991921, + 40.725203, + -73.982557, + 40.734816 + ], + "center": [ + -73.987361, + 40.729269 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -73.987361, + 40.729269 + ] + }, + "context": [ + { + "id": "postcode.5006143367295016", + "text": "10003" + }, + { + "id": "locality.338856684", + "mapbox_id": "dXJuOm1ieHBsYzpGREtLN0E", + "wikidata": "Q11299", + "text": "Manhattan" + }, + { + "id": "place.233720044", + "mapbox_id": "dXJuOm1ieHBsYzpEZTVJN0E", + "wikidata": "Q60", + "text": "New York" + }, + { + "id": "district.17000172", + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416", + "text": "New York County" + }, + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "postcode.5006143367295016", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "10003", + "place_name": "New York, New York 10003, United States", + "center": [ + -73.99044, + 40.73365 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -73.99044, + 40.73365 + ] + }, + "context": [ + { + "id": "locality.338856684", + "mapbox_id": "dXJuOm1ieHBsYzpGREtLN0E", + "wikidata": "Q11299", + "text": "Manhattan" + }, + { + "id": "place.233720044", + "mapbox_id": "dXJuOm1ieHBsYzpEZTVJN0E", + "wikidata": "Q60", + "text": "New York" + }, + { + "id": "district.17000172", + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416", + "text": "New York County" + }, + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "locality.338856684", + "type": "Feature", + "place_type": [ + "locality" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpGREtLN0E", + "wikidata": "Q11299" + }, + "text": "Manhattan", + "place_name": "Manhattan, New York, United States", + "bbox": [ + -74.0473132, + 40.679573, + -73.907, + 40.882075 + ], + "center": [ + -73.959894, + 40.789624 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -73.959894, + 40.789624 + ] + }, + "context": [ + { + "id": "place.233720044", + "mapbox_id": "dXJuOm1ieHBsYzpEZTVJN0E", + "wikidata": "Q60", + "text": "New York" + }, + { + "id": "district.17000172", + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416", + "text": "New York County" + }, + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "place.233720044", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpEZTVJN0E", + "wikidata": "Q60" + }, + "text": "New York", + "place_name": "New York, New York, United States", + "bbox": [ + -74.2596399, + 40.477399, + -73.700292, + 40.917577 + ], + "center": [ + -74.0059945, + 40.7127492 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -74.0059945, + 40.7127492 + ] + }, + "context": [ + { + "id": "district.17000172", + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416", + "text": "New York County" + }, + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "district.17000172", + "type": "Feature", + "place_type": [ + "district" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpBUU5tN0E", + "wikidata": "Q500416" + }, + "text": "New York County", + "place_name": "New York County, New York, United States", + "bbox": [ + -74.0517904, + 40.6692438, + -73.907007, + 40.8853224 + ], + "center": [ + -73.965633, + 40.777244 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -73.965633, + 40.777244 + ] + }, + "context": [ + { + "id": "region.107756", + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY", + "text": "New York" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "region.107756", + "type": "Feature", + "place_type": [ + "region" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpBYVRz", + "wikidata": "Q1384", + "short_code": "US-NY" + }, + "text": "New York", + "place_name": "New York, United States", + "bbox": [ + -79.8046875, + 40.4771401, + -71.763627, + 45.0239467 + ], + "center": [ + -75.4652471468304, + 42.751210955038 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -75.4652471468304, + 42.751210955038 + ] + }, + "context": [ + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "country.8940", + "type": "Feature", + "place_type": [ + "country" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us" + }, + "text": "United States", + "place_name": "United States", + "bbox": [ + -179.9, + 18.8164227, + -66.8847656, + 71.420291 + ], + "center": [ + -97.9222112121185, + 39.3812661305678 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -97.9222112121185, + 39.3812661305678 + ] + } + } + ], + "attribution": "NOTICE: © 2024 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare." +} \ No newline at end of file diff --git a/Tests/MapboxSearchUITests/MockWebServer/mapbox.places.san.francisco.json b/Tests/MapboxSearchUITests/MockWebServer/mapbox.places.san.francisco.json new file mode 100644 index 000000000..a8f0df3d6 --- /dev/null +++ b/Tests/MapboxSearchUITests/MockWebServer/mapbox.places.san.francisco.json @@ -0,0 +1,76 @@ +{ + "type": "FeatureCollection", + "query": [ + "san", + "francisco" + ], + "features": [ + { + "id": "place.292358380", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpFVzBJN0E", + "wikidata": "Q62" + }, + "text_en": "San Francisco", + "language_en": "en", + "place_name_en": "San Francisco, California, United States", + "text": "San Francisco", + "language": "en", + "place_name": "San Francisco, California, United States", + "bbox": [ + -122.5446375, + 37.670769, + -122.3010701, + 37.8664883 + ], + "center": [ + -122.419359, + 37.7792376 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -122.419359, + 37.7792376 + ] + }, + "context": [ + { + "id": "district.20547308", + "mapbox_id": "dXJuOm1ieHBsYzpBVG1HN0E", + "wikidata": "Q62", + "text_en": "San Francisco", + "language_en": "en", + "text": "San Francisco", + "language": "en" + }, + { + "id": "region.419052", + "mapbox_id": "dXJuOm1ieHBsYzpCbVRz", + "wikidata": "Q99", + "short_code": "US-CA", + "text_en": "California", + "language_en": "en", + "text": "California", + "language": "en" + }, + { + "id": "country.8940", + "mapbox_id": "dXJuOm1ieHBsYzpJdXc", + "wikidata": "Q30", + "short_code": "us", + "text_en": "United States", + "language_en": "en", + "text": "United States", + "language": "en" + } + ] + } + ], + "attribution": "NOTICE: © 2024 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare." +} diff --git a/Tests/MapboxSearchUITests/MockWebServer/reverse-geocoding.json b/Tests/MapboxSearchUITests/MockWebServer/reverse-geocoding-sbs.json similarity index 100% rename from Tests/MapboxSearchUITests/MockWebServer/reverse-geocoding.json rename to Tests/MapboxSearchUITests/MockWebServer/reverse-geocoding-sbs.json diff --git a/Tests/MapboxSearchUITests/VisibilityTestCase.swift b/Tests/MapboxSearchUITests/VisibilityTestCase.swift index 3d97742ec..d3cd54d4d 100644 --- a/Tests/MapboxSearchUITests/VisibilityTestCase.swift +++ b/Tests/MapboxSearchUITests/VisibilityTestCase.swift @@ -1,7 +1,5 @@ import XCTest -// swiftlint:disable empty_count - class VisibilityTestCase: BaseTestCase { override func setUpWithError() throws { try super.setUpWithError() @@ -42,29 +40,25 @@ class VisibilityTestCase: BaseTestCase { let searchBar = app.searchBar waitForHittable(searchBar) - XCTAssertTrue(app.isCollapsed) - waitForHittable(app.buttons["HotCategoryButton.fuel"], message: "Fuel category not hittable").tap() searchBar.swipeUp() - waitForHittable(app.buttons["HotCategoryButton.fuel"], message: "SwipeUp Fuel category not hittable").tap() + waitForHittable(app.buttons["HotCategoryButton.fuel"], timeout: 10, message: "Fuel category not hittable") + .tap() - XCTAssertTrue(app.isCollapsed) - waitForHittable(app.buttons["HotCategoryButton.parking"], message: "Parking category not hittable").tap() searchBar.swipeUp() - waitForHittable(app.buttons["HotCategoryButton.parking"], message: "SwipeUp Parking category not hittable") + waitForHittable(app.buttons["HotCategoryButton.parking"], timeout: 10, message: "Parking category not hittable") .tap() - XCTAssertTrue(app.isCollapsed) - waitForHittable(app.buttons["HotCategoryButton.restaurant"], message: "Restaurant category not hittable").tap() searchBar.swipeUp() waitForHittable( app.buttons["HotCategoryButton.restaurant"], - message: "SwipeUp Restaurant category not hittable" + timeout: 10, + message: "Restaurant category not hittable" ).tap() XCTAssertTrue(app.isCollapsed) - waitForHittable(app.buttons["HotCategoryButton.cafe"], message: "Cafe category not hittable").tap() searchBar.swipeUp() - waitForHittable(app.buttons["HotCategoryButton.cafe"], message: "SwipeUp Cafe category not hittable").tap() + waitForHittable(app.buttons["HotCategoryButton.cafe"], timeout: 10, message: "Cafe category not hittable") + .tap() } func testCategoriesList() throws {