diff --git a/Example/Podfile b/Example/Podfile index 9dd9cd2..0105363 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -13,6 +13,10 @@ target 'ReCaptcha_Example' do pod 'AppSwizzle', :git => 'https://github.com/fjcaetano/AppSwizzle.git', :branch => 'swift4' end + + target 'ReCaptcha_UITests' do + inherit! :search_paths + end end post_install do |i| diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 64dc964..66ad94d 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -37,6 +37,6 @@ SPEC CHECKSUMS: RxSwift: c6e3b1c7b325c7d121cd4327e9d98b7ed746b570 SwiftLint: 2e4b89feed5909c42c3735bbd6745f4345c4b772 -PODFILE CHECKSUM: 354a8d5b36f1deae996d24aea6382d1ca091466f +PODFILE CHECKSUM: 583c68236539bad71551001f4022b6f2e14d0438 COCOAPODS: 1.3.1 diff --git a/Example/ReCaptcha.xcodeproj/project.pbxproj b/Example/ReCaptcha.xcodeproj/project.pbxproj index 30394bd..7ddb559 100644 --- a/Example/ReCaptcha.xcodeproj/project.pbxproj +++ b/Example/ReCaptcha.xcodeproj/project.pbxproj @@ -12,12 +12,14 @@ 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; + 9D85E832734B73CFBD0156E0 /* Pods_ReCaptcha_UITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4C17A11F39B6DC940891AE0 /* Pods_ReCaptcha_UITests.framework */; }; BD850CB2DF4C9C94FC51226C /* Pods_ReCaptcha_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62BEEA62161F672468CCFD64 /* Pods_ReCaptcha_Example.framework */; }; D091B6E053FD250B4757E34C /* Pods_ReCaptcha_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9417A28DC340FF0BC1627B3F /* Pods_ReCaptcha_Tests.framework */; }; F206BAD51F8D3FEB00A25807 /* Cartfile in Resources */ = {isa = PBXBuildFile; fileRef = F206BAD41F8D3FEB00A25807 /* Cartfile */; }; F231B3971FEC325A00F82943 /* DispatchQueue__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F231B3961FEC325A00F82943 /* DispatchQueue__Tests.swift */; }; F231B39F1FED4A8C00F82943 /* ReCaptchaDecoder+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F231B39E1FED4A8C00F82943 /* ReCaptchaDecoder+Helper.swift */; }; F288E9451F9537760018688D /* ReCaptchaError+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F288E9441F9537760018688D /* ReCaptchaError+Equatable.swift */; }; + F28FAC9F200E425600E14987 /* ReCaptcha_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28FAC9E200E425600E14987 /* ReCaptcha_UITests.swift */; }; F2E2685E1F7AEE3400CD876D /* ReCaptcha__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2E2685D1F7AEE3400CD876D /* ReCaptcha__Tests.swift */; }; F2ECCF8A1E9FCEFE0097B199 /* ReCaptchaDecoder__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2ECCF891E9FCEFE0097B199 /* ReCaptchaDecoder__Tests.swift */; }; F2ECCF8C1E9FE37C0097B199 /* mock.html in Resources */ = {isa = PBXBuildFile; fileRef = F2ECCF8B1E9FE37C0097B199 /* mock.html */; }; @@ -28,6 +30,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + F28FACA1200E425600E14987 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 607FACC81AFB9204008FA782 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 607FACCF1AFB9204008FA782; + remoteInfo = ReCaptcha_Example; + }; F2ECCF7B1E9FC47B0097B199 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 607FACC81AFB9204008FA782 /* Project object */; @@ -40,6 +49,7 @@ /* Begin PBXFileReference section */ 0A2D0E5B4C6E445BF971488B /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 44568771DD76CFBDF2D1C83D /* Pods-ReCaptcha_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_Tests/Pods-ReCaptcha_Tests.release.xcconfig"; sourceTree = ""; }; + 4A242A5E18CBBFA095B66558 /* Pods-ReCaptcha_UITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_UITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_UITests/Pods-ReCaptcha_UITests.release.xcconfig"; sourceTree = ""; }; 4FED8267564AACFFEE83DB15 /* Pods-ReCaptcha_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_Tests/Pods-ReCaptcha_Tests.debug.xcconfig"; sourceTree = ""; }; 607FACD01AFB9204008FA782 /* ReCaptcha_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReCaptcha_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -51,7 +61,9 @@ 62BEEA62161F672468CCFD64 /* Pods_ReCaptcha_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReCaptcha_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 62C1DD0E80E9920845E5DA51 /* ReCaptcha.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = ReCaptcha.podspec; path = ../ReCaptcha.podspec; sourceTree = ""; }; 80FF4E03D71AACBD81A36301 /* Pods-ReCaptcha_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_Example/Pods-ReCaptcha_Example.debug.xcconfig"; sourceTree = ""; }; + 930BD5ACA20B973070B89ACF /* Pods-ReCaptcha_UITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_UITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_UITests/Pods-ReCaptcha_UITests.debug.xcconfig"; sourceTree = ""; }; 9417A28DC340FF0BC1627B3F /* Pods_ReCaptcha_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReCaptcha_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4C17A11F39B6DC940891AE0 /* Pods_ReCaptcha_UITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ReCaptcha_UITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C2A0BDD35B5E219129E9BC65 /* Pods-ReCaptcha_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ReCaptcha_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-ReCaptcha_Example/Pods-ReCaptcha_Example.release.xcconfig"; sourceTree = ""; }; C8537003ECC47117AF54DCA9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; F206BAD41F8D3FEB00A25807 /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Cartfile; path = ../Cartfile; sourceTree = ""; }; @@ -59,6 +71,9 @@ F231B3961FEC325A00F82943 /* DispatchQueue__Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchQueue__Tests.swift; sourceTree = ""; }; F231B39E1FED4A8C00F82943 /* ReCaptchaDecoder+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReCaptchaDecoder+Helper.swift"; sourceTree = ""; }; F288E9441F9537760018688D /* ReCaptchaError+Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReCaptchaError+Equatable.swift"; sourceTree = ""; }; + F28FAC9C200E425600E14987 /* ReCaptcha_UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReCaptcha_UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + F28FAC9E200E425600E14987 /* ReCaptcha_UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReCaptcha_UITests.swift; sourceTree = ""; }; + F28FACA0200E425600E14987 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F2E2685D1F7AEE3400CD876D /* ReCaptcha__Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReCaptcha__Tests.swift; sourceTree = ""; }; F2ECCF761E9FC47B0097B199 /* ReCaptcha_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReCaptcha_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; F2ECCF7A1E9FC47B0097B199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -79,6 +94,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28FAC99200E425600E14987 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9D85E832734B73CFBD0156E0 /* Pods_ReCaptcha_UITests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F2ECCF731E9FC47B0097B199 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -96,6 +119,7 @@ 607FACF51AFB993E008FA782 /* Podspec Metadata */, 607FACD21AFB9204008FA782 /* Example for ReCaptcha */, F2ECCF771E9FC47B0097B199 /* ReCaptcha_Tests */, + F28FAC9D200E425600E14987 /* ReCaptcha_UITests */, 607FACD11AFB9204008FA782 /* Products */, 716E2370DBF48D5E2C86E802 /* Pods */, FDC29111B59FAB9F0F44DADB /* Frameworks */, @@ -107,6 +131,7 @@ children = ( 607FACD01AFB9204008FA782 /* ReCaptcha_Example.app */, F2ECCF761E9FC47B0097B199 /* ReCaptcha_Tests.xctest */, + F28FAC9C200E425600E14987 /* ReCaptcha_UITests.xctest */, ); name = Products; sourceTree = ""; @@ -152,10 +177,21 @@ C2A0BDD35B5E219129E9BC65 /* Pods-ReCaptcha_Example.release.xcconfig */, 4FED8267564AACFFEE83DB15 /* Pods-ReCaptcha_Tests.debug.xcconfig */, 44568771DD76CFBDF2D1C83D /* Pods-ReCaptcha_Tests.release.xcconfig */, + 930BD5ACA20B973070B89ACF /* Pods-ReCaptcha_UITests.debug.xcconfig */, + 4A242A5E18CBBFA095B66558 /* Pods-ReCaptcha_UITests.release.xcconfig */, ); name = Pods; sourceTree = ""; }; + F28FAC9D200E425600E14987 /* ReCaptcha_UITests */ = { + isa = PBXGroup; + children = ( + F28FAC9E200E425600E14987 /* ReCaptcha_UITests.swift */, + F28FACA0200E425600E14987 /* Info.plist */, + ); + path = ReCaptcha_UITests; + sourceTree = ""; + }; F2ECCF771E9FC47B0097B199 /* ReCaptcha_Tests */ = { isa = PBXGroup; children = ( @@ -203,6 +239,7 @@ children = ( 62BEEA62161F672468CCFD64 /* Pods_ReCaptcha_Example.framework */, 9417A28DC340FF0BC1627B3F /* Pods_ReCaptcha_Tests.framework */, + B4C17A11F39B6DC940891AE0 /* Pods_ReCaptcha_UITests.framework */, ); name = Frameworks; sourceTree = ""; @@ -231,6 +268,28 @@ productReference = 607FACD01AFB9204008FA782 /* ReCaptcha_Example.app */; productType = "com.apple.product-type.application"; }; + F28FAC9B200E425600E14987 /* ReCaptcha_UITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F28FACA5200E425600E14987 /* Build configuration list for PBXNativeTarget "ReCaptcha_UITests" */; + buildPhases = ( + B8A66872166B84DAD39A3E1F /* [CP] Check Pods Manifest.lock */, + F28FAC98200E425600E14987 /* Sources */, + F28FAC99200E425600E14987 /* Frameworks */, + F28FAC9A200E425600E14987 /* Resources */, + BF2909E4520B29BFFBC94AD6 /* [CP] Embed Pods Frameworks */, + DCB1D99E77E589CD76CD3186 /* [CP] Copy Pods Resources */, + F28FACA6200E447600E14987 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + F28FACA2200E425600E14987 /* PBXTargetDependency */, + ); + name = ReCaptcha_UITests; + productName = ReCaptcha_UITests; + productReference = F28FAC9C200E425600E14987 /* ReCaptcha_UITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; F2ECCF751E9FC47B0097B199 /* ReCaptcha_Tests */ = { isa = PBXNativeTarget; buildConfigurationList = F2ECCF7D1E9FC47B0097B199 /* Build configuration list for PBXNativeTarget "ReCaptcha_Tests" */; @@ -258,7 +317,7 @@ 607FACC81AFB9204008FA782 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0830; + LastSwiftUpdateCheck = 0910; LastUpgradeCheck = 0900; ORGANIZATIONNAME = ReCaptcha; TargetAttributes = { @@ -266,9 +325,13 @@ CreatedOnToolsVersion = 6.3.1; LastSwiftMigration = 0900; }; + F28FAC9B200E425600E14987 = { + CreatedOnToolsVersion = 9.1; + ProvisioningStyle = Automatic; + TestTargetID = 607FACCF1AFB9204008FA782; + }; F2ECCF751E9FC47B0097B199 = { CreatedOnToolsVersion = 8.3; - DevelopmentTeam = 58EEZG76L8; LastSwiftMigration = 0900; ProvisioningStyle = Automatic; TestTargetID = 607FACCF1AFB9204008FA782; @@ -290,6 +353,7 @@ targets = ( 607FACCF1AFB9204008FA782 /* ReCaptcha_Example */, F2ECCF751E9FC47B0097B199 /* ReCaptcha_Tests */, + F28FAC9B200E425600E14987 /* ReCaptcha_UITests */, ); }; /* End PBXProject section */ @@ -306,6 +370,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28FAC9A200E425600E14987 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; F2ECCF741E9FC47B0097B199 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -392,6 +463,54 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReCaptcha_Example/Pods-ReCaptcha_Example-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + B8A66872166B84DAD39A3E1F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ReCaptcha_UITests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + BF2909E4520B29BFFBC94AD6 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReCaptcha_UITests/Pods-ReCaptcha_UITests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + DCB1D99E77E589CD76CD3186 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ReCaptcha_UITests/Pods-ReCaptcha_UITests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; DDB47454887253730AB35230 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -439,6 +558,19 @@ shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/SwiftLint/swiftlint\" --path \"${PROJECT_DIR}/..\""; }; + F28FACA6200E447600E14987 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Unfortuantely, Xcode 7.3 and Cocoapods are not yet fully compatible. The location of the xctest bundle has changed and so we need to manually copy some things ...\n# this fix is necesary - tested on Cocoapods 1.1.rc2 that still have the issue.\n# ver 0.2\n\n# set variables\nBUILD_ROOT=\"${BUILT_PRODUCTS_DIR}\"\n\nMAIN_TARGET_NAME=\"ReCaptcha_Example.app\" #if you know how to get this from here do let me know!\nMAIN_TARGET_FRAMEWORKS=\"${BUILT_PRODUCTS_DIR}/${MAIN_TARGET_NAME}/Frameworks\"\n\nTEST_TARGET_NAME=\"ReCaptcha_UITests\"\nTEST_RUNNER_TARGET_FRAMEWORKS=\"${BUILT_PRODUCTS_DIR}/${TEST_TARGET_NAME}-Runner.app\"\n\n# COPY FRAMEWORKS FROM MAIN TARGET TO TEST TARGET if framework folder exists\nif [[ -d \"${MAIN_TARGET_FRAMEWORKS}\" ]]; then\necho \"**** COPYING FRAMEWORKS FROM \\\"${MAIN_TARGET_FRAMEWORKS}\\\" TO \\\"${TEST_RUNNER_TARGET_FRAMEWORKS}\\\" ...\"\ncp -R \"${MAIN_TARGET_FRAMEWORKS}\" \"${TEST_RUNNER_TARGET_FRAMEWORKS}\"\nfi\n\n# You don't really need this section below if your script works, otherwise it is quite helpful to troubleshoot any problems with paths.\n\n# DEBUG SECTION\necho \"BUILD_ROOT : ${BUILD_ROOT}\"\necho \"MAIN_TARGET_NAME : ${MAIN_TARGET_NAME}\"\necho \"MAIN_TARGET_FRAMEWORKS ${MAIN_TARGET_FRAMEWORKS}\"\necho \"TEST_TARGET_NAME : ${TEST_TARGET_NAME}\"\necho \"TEST_RUNNER_TARGET_FRAMEWORKS : ${TEST_TARGET_FRAMEWORKS}\"\necho \"CONTENT: ${CONTENTS_FOLDER_PATH}\"\necho \"FRAMEWORK PATH: ${FRAMEWORKS_FOLDER_PATH}\"\necho \"TARGET BUILD DIR: ${TARGET_BUILD_DIR}\""; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -451,6 +583,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28FAC98200E425600E14987 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F28FAC9F200E425600E14987 /* ReCaptcha_UITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F2ECCF721E9FC47B0097B199 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -470,6 +610,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + F28FACA2200E425600E14987 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 607FACCF1AFB9204008FA782 /* ReCaptcha_Example */; + targetProxy = F28FACA1200E425600E14987 /* PBXContainerItemProxy */; + }; F2ECCF7C1E9FC47B0097B199 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 607FACCF1AFB9204008FA782 /* ReCaptcha_Example */; @@ -628,6 +773,54 @@ }; name = Release; }; + F28FACA3200E425600E14987 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 930BD5ACA20B973070B89ACF /* Pods-ReCaptcha_UITests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ReCaptcha_UITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ReCaptcha.ReCaptcha-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ReCaptcha_Example; + }; + name = Debug; + }; + F28FACA4200E425600E14987 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4A242A5E18CBBFA095B66558 /* Pods-ReCaptcha_UITests.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ReCaptcha_UITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ReCaptcha.ReCaptcha-UITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = ReCaptcha_Example; + }; + name = Release; + }; F2ECCF7E1E9FC47B0097B199 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4FED8267564AACFFEE83DB15 /* Pods-ReCaptcha_Tests.debug.xcconfig */; @@ -637,9 +830,9 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = 58EEZG76L8; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = ReCaptcha_Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.flaviocaetano.ReCaptcha-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -658,9 +851,9 @@ CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - DEVELOPMENT_TEAM = 58EEZG76L8; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = ReCaptcha_Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.flaviocaetano.ReCaptcha-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -691,6 +884,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F28FACA5200E425600E14987 /* Build configuration list for PBXNativeTarget "ReCaptcha_UITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F28FACA3200E425600E14987 /* Debug */, + F28FACA4200E425600E14987 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F2ECCF7D1E9FC47B0097B199 /* Build configuration list for PBXNativeTarget "ReCaptcha_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Example/ReCaptcha.xcodeproj/xcshareddata/xcschemes/ReCaptcha-Example.xcscheme b/Example/ReCaptcha.xcodeproj/xcshareddata/xcschemes/ReCaptcha-Example.xcscheme index 1e4fae5..81d7408 100644 --- a/Example/ReCaptcha.xcodeproj/xcshareddata/xcschemes/ReCaptcha-Example.xcscheme +++ b/Example/ReCaptcha.xcodeproj/xcshareddata/xcschemes/ReCaptcha-Example.xcscheme @@ -54,6 +54,16 @@ ReferencedContainer = "container:ReCaptcha.xcodeproj"> + + + + - + - + @@ -36,14 +36,26 @@ + + + + + + + + + + + @@ -52,10 +64,12 @@ + + diff --git a/Example/ReCaptcha/ViewController.swift b/Example/ReCaptcha/ViewController.swift index 486f516..1d03b05 100644 --- a/Example/ReCaptcha/ViewController.swift +++ b/Example/ReCaptcha/ViewController.swift @@ -14,27 +14,33 @@ import UIKit class ViewController: UIViewController { - fileprivate static let webViewTag = 123 + private struct Constants { + static let webViewTag = 123 + } - // swiftlint:disable:next force_try - fileprivate let recaptcha = try! ReCaptcha() - fileprivate var disposeBag = DisposeBag() + private var recaptcha: ReCaptcha! + private var disposeBag = DisposeBag() - @IBOutlet weak var label: UILabel! - @IBOutlet weak var spinner: UIActivityIndicatorView! + @IBOutlet private weak var label: UILabel! + @IBOutlet private weak var spinner: UIActivityIndicatorView! + @IBOutlet private weak var segmentedControl: UISegmentedControl! override func viewDidLoad() { super.viewDidLoad() + setupReCaptcha(endpoint: .default) + } - recaptcha.configureWebView { [weak self] webview in - webview.frame = self?.view.bounds ?? CGRect.zero - webview.tag = ViewController.webViewTag + @IBAction func didPressSegmentedControl(_ sender: UISegmentedControl) { + label.text = "" + switch sender.selectedSegmentIndex { + case 0: setupReCaptcha(endpoint: .default) + case 1: setupReCaptcha(endpoint: .alternate) + default: assertionFailure("invalid index") } } - - @IBAction func didPressButton(button: UIButton) { + @IBAction private func didPressButton(button: UIButton) { disposeBag = DisposeBag() let validate = recaptcha.rx.validate(on: view) @@ -44,20 +50,28 @@ class ViewController: UIViewController { let isLoading = validate .map { _ in false } .startWith(true) + .share(replay: 1) isLoading .bind(to: spinner.rx.isAnimating) .disposed(by: disposeBag) - isLoading + let isEnabled = isLoading .map { !$0 } .catchErrorJustReturn(false) + .share(replay: 1) + + isEnabled .bind(to: button.rx.isEnabled) .disposed(by: disposeBag) + isEnabled + .bind(to: segmentedControl.rx.isEnabled) + .disposed(by: disposeBag) + validate .map { [weak self] _ in - self?.view.viewWithTag(ViewController.webViewTag) + self?.view.viewWithTag(Constants.webViewTag) } .subscribe(onNext: { subview in subview?.removeFromSuperview() @@ -69,4 +83,20 @@ class ViewController: UIViewController { .bind(to: label.rx.text) .disposed(by: disposeBag) } + + private func setupReCaptcha(endpoint: ReCaptcha.Endpoint) { + // swiftlint:disable:next force_try + recaptcha = try! ReCaptcha(endpoint: endpoint) + + recaptcha.configureWebView { [weak self] webview in + webview.frame = self?.view.bounds ?? CGRect.zero + webview.tag = Constants.webViewTag + + // For testing purposes + // If the webview requires presentation, this should work as a way of detecting the webview in UI tests + let label = UILabel(frame: CGRect(x: 0, y: 0, width: 1, height: 1)) + label.accessibilityLabel = "webview" + self?.view.addSubview(label) + } + } } diff --git a/Example/ReCaptcha_UITests/.swiftlint.yml b/Example/ReCaptcha_UITests/.swiftlint.yml new file mode 100644 index 0000000..2d9f9c0 --- /dev/null +++ b/Example/ReCaptcha_UITests/.swiftlint.yml @@ -0,0 +1,5 @@ +disabled_rules: + - type_name + - nesting + - force_unwrapping + - explicit_top_level_acl diff --git a/Example/ReCaptcha_UITests/Info.plist b/Example/ReCaptcha_UITests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Example/ReCaptcha_UITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Example/ReCaptcha_UITests/ReCaptcha_UITests.swift b/Example/ReCaptcha_UITests/ReCaptcha_UITests.swift new file mode 100644 index 0000000..21098e0 --- /dev/null +++ b/Example/ReCaptcha_UITests/ReCaptcha_UITests.swift @@ -0,0 +1,62 @@ +// +// ReCaptcha_UITests.swift +// ReCaptcha +// +// Created by Flávio Caetano on 16/01/18. +// Copyright © 2018 ReCaptcha. All rights reserved. +// + +import Foundation +@testable import ReCaptcha +@testable import ReCaptcha_Example +import XCTest + +class ReCaptcha_UITests: XCTestCase { + + override func setUp() { + super.setUp() + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + XCUIApplication().launch() + } + + func test__Validate__Default_Endpoint() { + let app = XCUIApplication() + app.segmentedControls.buttons["Default"].tap() + app.buttons["Validate"].tap() + + verifyValidation() + } + + func test__Validate__Alternate_Endpoint() { + let app = XCUIApplication() + app.segmentedControls.buttons["Alternate"].tap() + app.buttons["Validate"].tap() + + verifyValidation() + } + + // MARK: Private Methods + + private func verifyValidation() { + let app = XCUIApplication() + let webview = app.staticTexts.element(matching: .any, identifier: "webview") + let webviewExists = webview.waitForExistence(timeout: 10) + + if webviewExists { + // Did show recaptcha to the user + // Assumes endpoint and comms are working correctly + print("WEBVIEW DETECTED") + } + else { + let label = app.staticTexts.element(matching: .any, identifier: "resultLabel") + _ = label.waitForExistence(timeout: 10) + + XCTAssertFalse(label.label.isEmpty) + // Did automatically resolve the challenge + // Endpoint and comms are working correctly + print("LABEL WITH CONTENT") + } + } +} diff --git a/ReCaptcha/Classes/ReCaptchaWebViewManager.swift b/ReCaptcha/Classes/ReCaptchaWebViewManager.swift index 2db6091..ddecfee 100644 --- a/ReCaptcha/Classes/ReCaptchaWebViewManager.swift +++ b/ReCaptcha/Classes/ReCaptchaWebViewManager.swift @@ -126,6 +126,8 @@ open class ReCaptchaWebViewManager { configuration: self.buildConfiguration() ) webview.navigationDelegate = self.webviewDelegate + webview.accessibilityIdentifier = "webview" + webview.accessibilityTraits = UIAccessibilityTraitLink webview.isHidden = true return webview diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 09708cf..3e16b8f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -10,10 +10,9 @@ default_platform :ios platform :ios do skip_docs - devices = ["iPhone X (11.0)"] - devices << "iPhone 7 (10.0)" if !Helper.is_ci? - devices << "iPhone 6 (9.0)" if !Helper.is_ci? - devices << "iPhone 5s (8.1)" if !Helper.is_ci? + devices = [["iPhone X", "11"]] + devices << ["iPhone 7", "10"] if !Helper.is_ci? + devices << ["iPhone 5s", "9"] if !Helper.is_ci? desc "Runs the following lanes:\n- test\n- pod_lint\n- carthage_lint" lane :ci do @@ -42,7 +41,7 @@ platform :ios do # https://stackoverflow.com/questions/37922146/xctests-failing-on-physical-device-canceling-tests-due-to-timeout/40790171#40790171 scan( build_for_testing: true, - devices: devices, + devices: self.select_similar_simulator(devices), scheme: "ReCaptcha-Example", workspace: "Example/ReCaptcha.xcworkspace", code_coverage: true, @@ -50,7 +49,7 @@ platform :ios do scan( test_without_building: true, - devices: devices, + devices: self.select_similar_simulator(devices), scheme: "ReCaptcha-Example", workspace: "Example/ReCaptcha.xcworkspace", code_coverage: true, @@ -125,18 +124,15 @@ platform :ios do ) end - after_all do |lane| - # This block is called, only if the executed lane was successful + # Private - # slack( - # message: "Successfully deployed new App Update." - # ) - end - - error do |lane, exception| - # slack( - # message: exception.message, - # success: false - # ) + def select_similar_simulator(args) + args.map { |name, ver| + FastlaneCore::Simulator.all + .select { |s| s.name == name } + .sort_by { |s| Gem::Version.create(s.os_version) } + .detect { |s| s.ios_version.start_with?(ver) } + } + .map { |s| "#{s.name} (#{s.ios_version})"} end end