diff --git a/.travis.yml b/.travis.yml index fe20bf9ce..f0beb4d6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c cache: cocoapods # pod install somtimes takes >20 minutes, so lets cache this -osx_image: xcode8.2 +osx_image: xcode8.3 env: -EARLY_START_SIMULATOR=1 # early starting simulator reduces false negatives due to test timeouts @@ -9,11 +9,8 @@ env: before_install: - brew update # we may not be running the latest version so always update - brew outdated xctool || brew upgrade xctool # only upgrade if outdated (saves 2 minutes) - - gem install cocoapods # get the latest cocoapods - - gem install xcpretty - - travis_wait 20 pod repo update --silent # log output is too long without --silent + - bundle + - bundle exec pod repo update --silent # log output is too long without --silent -install: travis_wait 30 pod install # OpenSSL takes a long time to compile - -script: make ci +script: make ci_scan diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..0814db77a --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org' + +gem 'cocoapods' +gem 'fastlane' + diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..3d0a51079 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,189 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.5) + activesupport (4.2.9) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.1) + public_suffix (~> 2.0, >= 2.0.2) + babosa (1.0.2) + claide (1.0.2) + cocoapods (1.2.1) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.2.1) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.3, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-stats (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.2.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.5.7) + nap (~> 1.0) + ruby-macho (~> 1.1) + xcodeproj (>= 1.4.4, < 2.0) + cocoapods-core (1.2.1) + activesupport (>= 4.0.2, < 5) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.1) + cocoapods-downloader (1.1.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.2.0) + nap (>= 0.8, < 2.0) + netrc (= 0.7.8) + cocoapods-try (1.1.0) + colored (1.2) + colored2 (3.1.2) + commander-fastlane (4.4.5) + highline (~> 1.7.2) + declarative (0.0.9) + declarative-option (0.1.0) + domain_name (0.5.20170404) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.2.1) + escape (0.0.4) + excon (0.57.1) + faraday (0.12.1) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.6) + faraday (>= 0.7.4) + http-cookie (~> 1.0.0) + faraday_middleware (0.11.0.1) + faraday (>= 0.7.4, < 1.0) + fastimage (2.1.0) + fastlane (2.46.0) + CFPropertyList (>= 2.3, < 3.0.0) + addressable (>= 2.3, < 3.0.0) + babosa (>= 1.0.2, < 2.0.0) + bundler (>= 1.12.0, < 2.0.0) + colored + commander-fastlane (>= 4.4.5, < 5.0.0) + dotenv (>= 2.1.1, < 3.0.0) + excon (>= 0.45.0, < 1.0.0) + faraday (~> 0.9) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 0.9) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.0.1, < 2.0.0) + google-api-client (>= 0.12.0, < 0.13.0) + highline (>= 1.7.2, < 2.0.0) + json (< 3.0.0) + mini_magick (~> 4.5.1) + multi_json + multi_xml (~> 0.5) + multipart-post (~> 2.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 1.1.0, < 2.0.0) + security (= 0.1.3) + slack-notifier (>= 1.3, < 2.0.0) + terminal-notifier (>= 1.6.2, < 2.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (~> 0.5.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.4.4, < 2.0.0) + xcpretty (>= 0.2.4, < 1.0.0) + xcpretty-travis-formatter (>= 0.0.3) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.0.3) + google-api-client (0.12.0) + addressable (~> 2.5, >= 2.5.1) + googleauth (~> 0.5) + httpclient (>= 2.8.1, < 3.0) + mime-types (~> 3.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + googleauth (0.5.1) + faraday (~> 0.9) + jwt (~> 1.4) + logging (~> 2.0) + memoist (~> 0.12) + multi_json (~> 1.11) + os (~> 0.9) + signet (~> 0.7) + highline (1.7.8) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + i18n (0.8.4) + json (2.1.0) + jwt (1.5.6) + little-plugger (1.1.4) + logging (2.2.2) + little-plugger (~> 1.1) + multi_json (~> 1.10) + memoist (0.16.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_magick (4.5.1) + minitest (5.10.2) + molinillo (0.5.7) + multi_json (1.12.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nanaimo (0.2.3) + nap (1.1.0) + netrc (0.7.8) + os (0.9.6) + plist (3.3.0) + public_suffix (2.0.5) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.0.2) + rouge (2.0.7) + ruby-macho (1.1.0) + rubyzip (1.2.1) + security (0.1.3) + signet (0.7.3) + addressable (~> 2.3) + faraday (~> 0.9) + jwt (~> 1.5) + multi_json (~> 1.10) + slack-notifier (1.5.1) + terminal-notifier (1.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thread_safe (0.3.6) + tty-screen (0.5.0) + tzinfo (1.2.3) + thread_safe (~> 0.1) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.4) + unicode-display_width (1.3.0) + word_wrap (1.0.0) + xcodeproj (1.5.0) + CFPropertyList (~> 2.3.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.3) + xcpretty (0.2.8) + rouge (~> 2.0.7) + xcpretty-travis-formatter (0.0.4) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods + fastlane + +BUNDLED WITH + 1.14.6 diff --git a/Makefile b/Makefile index a7ee23774..da7cdc3ac 100644 --- a/Makefile +++ b/Makefile @@ -14,20 +14,25 @@ default: test ci: dependencies test +ci_scan: dependencies scan + update_dependencies: - pod update + bundle exec pod update carthage update --platform iOS dependencies: cd $(WORKING_DIR) && \ git submodule update --init - pod install + bundle exec pod install carthage build --platform iOS build: dependencies cd $(WORKING_DIR) && \ $(XCODE_BUILD) build | xcpretty +scan: + bundle exec fastlane scan + test: optional_early_start_simulator cd $(WORKING_DIR) && \ $(XCODE_BUILD) \ diff --git a/Podfile b/Podfile index f6a3ff716..f3972ab16 100644 --- a/Podfile +++ b/Podfile @@ -13,6 +13,34 @@ target 'Signal' do #pod 'SignalServiceKit', path: '../SignalServiceKit' pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git' target 'SignalTests' do - inherit! :search_paths + inherit! :search_paths end + + post_install do |installer| + # Disable some asserts when building for tests + set_building_for_tests_config(installer, 'SignalServiceKit') + end +end + +# There are some asserts and debug checks that make testing difficult - e.g. Singleton asserts +def set_building_for_tests_config(installer, target_name) + target = installer.pods_project.targets.detect { |target| target.to_s == target_name } + if target == nil + throw "failed to find target: #{target_name}" + end + + build_config_name = "Test" + build_config = target.build_configurations.detect { |config| config.to_s == build_config_name } + if build_config == nil + throw "failed to find config: #{build_config_name} for target: #{target_name}" + end + + puts "--[!] Disabling singleton enforcement for target: #{target} in config: #{build_config}" + existing_definitions = build_config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] + + if existing_definitions == nil || existing.length == 0 + existing_definitions = "$(inheritied)" + end + build_config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = "#{existing_definitions} POD_CONFIGURATION_TEST=1 COCOAPODS=1 SSK_BUILDING_FOR_TESTS=1" end + diff --git a/Podfile.lock b/Podfile.lock index bbeaabfbf..62bee67b0 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -164,6 +164,6 @@ SPEC CHECKSUMS: UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d YapDatabase: cd911121580ff16675f65ad742a9eb0ab4d9e266 -PODFILE CHECKSUM: 4a21cd1bb2804a399fe7f9b696bd2f591f1df663 +PODFILE CHECKSUM: 23e9e80dd9f88092af75b917d37a459cfad37b7c COCOAPODS: 1.2.1 diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 77f4d5bf5..29412106e 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -109,6 +109,11 @@ 4517642B1DE939FD00EDB8B9 /* ContactCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451764291DE939FD00EDB8B9 /* ContactCell.swift */; }; 451A13B11E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451A13B01E13DED2000A50FD /* CallNotificationsAdapter.swift */; }; 451A13B21E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451A13B01E13DED2000A50FD /* CallNotificationsAdapter.swift */; }; + 451DA3C71F148986008E2423 /* SafetyNumberConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4585C4671ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift */; }; + 451DA3C81F14898E008E2423 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E2E91F1E153B3D00457AA0 /* Strings.swift */; }; + 451DA3C91F1489BE008E2423 /* OWSAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3453D8E91EC0D4ED003F9E6F /* OWSAlerts.swift */; }; + 451DA3CA1F148A9F008E2423 /* DeviceSleepManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 348F2EAD1F0D21BC00D4ECE0 /* DeviceSleepManager.swift */; }; + 451DA3CB1F148AAD008E2423 /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83B1E8DF1700035BE1A /* CallViewController.swift */; }; 451DE9F81DC18C9500810E42 /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45CD81EE1DC030E7004C9430 /* AccountManager.swift */; }; 451DE9FD1DC1A28200810E42 /* SyncPushTokensJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451DE9FC1DC1A28200810E42 /* SyncPushTokensJob.swift */; }; 451DE9FE1DC1A28200810E42 /* SyncPushTokensJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451DE9FC1DC1A28200810E42 /* SyncPushTokensJob.swift */; }; @@ -366,6 +371,7 @@ /* Begin PBXFileReference section */ 1B5E7D6C9007F5E5761D79DD /* libPods-SignalTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SignalTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Signal.test.xcconfig"; path = "Pods/Target Support Files/Pods-Signal/Pods-Signal.test.xcconfig"; sourceTree = ""; }; 34009B651EC4CB11001D95D1 /* OWSMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMath.h; sourceTree = ""; }; 3400C7901EAF89CD008A8584 /* SendExternalFileViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendExternalFileViewController.h; sourceTree = ""; }; 3400C7911EAF89CD008A8584 /* SendExternalFileViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SendExternalFileViewController.m; sourceTree = ""; }; @@ -671,6 +677,7 @@ 76EB052E18170B33006006FC /* ContactTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactTableViewCell.h; sourceTree = ""; }; 76EB052F18170B33006006FC /* ContactTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactTableViewCell.m; sourceTree = ""; }; 7DB8EE72F8522189E3E2CB45 /* libPods-Signal.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Signal.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8981C8F64D94D3C52EB67A2C /* Pods-SignalTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalTests/Pods-SignalTests.test.xcconfig"; sourceTree = ""; }; 954AEE681DF33D32002E5410 /* ContactsPickerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPickerTest.swift; sourceTree = ""; }; A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; @@ -1427,6 +1434,8 @@ DF728B4B438716EAF95CEC18 /* Pods-Signal.app store release.xcconfig */, AD2AB1207E8888E4262D781B /* Pods-SignalTests.debug.xcconfig */, E85DB184824BA9DC302EC8B3 /* Pods-SignalTests.app store release.xcconfig */, + 1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */, + 8981C8F64D94D3C52EB67A2C /* Pods-SignalTests.test.xcconfig */, ); name = Pods; sourceTree = ""; @@ -2269,9 +2278,11 @@ files = ( 4505C2C31E648F7A00CEBF41 /* ExperienceUpgradeFinder.swift in Sources */, 456F6E241E24133E00FD2210 /* CallKitCallUIAdaptee.swift in Sources */, + 451DA3C81F14898E008E2423 /* Strings.swift in Sources */, 456F6E251E24216100FD2210 /* DataChannelMessage.swift in Sources */, 452ECA4E1E087E7200E2F016 /* MessageFetcherJob.swift in Sources */, 45F170AD1E2F0351003FC1F2 /* CallAudioSession.swift in Sources */, + 451DA3C71F148986008E2423 /* SafetyNumberConfirmationAlert.swift in Sources */, 45C0DC1C1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */, 45F170BC1E2FC5D3003FC1F2 /* CallAudioService.swift in Sources */, 456F6E2F1E261D1000FD2210 /* PeerConnectionClientTest.swift in Sources */, @@ -2282,6 +2293,7 @@ B660F71B1C29988E00687D6E /* Environment.m in Sources */, B660F71C1C29988E00687D6E /* DebugLogger.m in Sources */, B660F71F1C29988E00687D6E /* PropertyListPreferences.m in Sources */, + 451DA3CA1F148A9F008E2423 /* DeviceSleepManager.swift in Sources */, B660F7201C29988E00687D6E /* Release.m in Sources */, 45BB93391E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, B660F7211C29988E00687D6E /* SignalKeyingStorage.m in Sources */, @@ -2306,6 +2318,7 @@ 451A13B21E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */, 45C681B81D305A580050903A /* OWSCall.m in Sources */, 4542F0971EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */, + 451DA3C91F1489BE008E2423 /* OWSAlerts.swift in Sources */, 45855F381D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */, 45DF5DF31DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */, 456AC8341E3A775E00A3C7FC /* Weak.swift in Sources */, @@ -2335,6 +2348,7 @@ 45C9DEB91DF4E35A0065CA84 /* WebRTCCallMessageHandler.swift in Sources */, B660F6DB1C29868000687D6E /* FunctionalUtilTest.m in Sources */, 45E7A6A81E71CA7E00D44FB5 /* DisplayableTextFilterTest.swift in Sources */, + 451DA3CB1F148AAD008E2423 /* CallViewController.swift in Sources */, 456F6E201E2411A000FD2210 /* CallService.swift in Sources */, 45E615171E8C59100018AD52 /* DisplayableTextFilter.swift in Sources */, B660F6DF1C29868000687D6E /* QueueTest.m in Sources */, @@ -2405,6 +2419,195 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 451DA3CC1F152887008E2423 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_RECEIVER_WEAK = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( + "DEBUG=1", + "$(inherited)", + "SSK_BUILDING_FOR_TESTS=1", + ); + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ""; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "-fobjc-arc-exceptions"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Test; + }; + 451DA3CD1F152887008E2423 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1CE3CD5C23334683BDD3D78C /* Pods-Signal.test.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Signal/Signal.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = U68MSDN6DR; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Signal/Signal-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + HAVE_CONFIG_H, + ); + GCC_STRICT_ALIASING = NO; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "\"${SRCROOT}/RedPhone/lib/ogg/include\"", + "\"${SRCROOT}/RedPhone/lib/debug/include\"", + "\"$(SRCROOT)/libtommath\"", + "\"$(SRCROOT)/libtomcrypt/headers\"", + "\"$(SRCROOT)/MMDrawerController\"", + "\"$(SRCROOT)/Libraries\"/**", + ); + INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)", + ); + LLVM_LTO = NO; + OTHER_LDFLAGS = "$(inherited)"; + PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.signal; + PRODUCT_NAME = Signal; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/Signal-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TEST_AFTER_BUILD = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + WRAPPER_EXTENSION = app; + }; + name = Test; + }; + 451DA3CE1F152887008E2423 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8981C8F64D94D3C52EB67A2C /* Pods-SignalTests.test.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEFINES_MODULE = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_GENERATE_TEST_COVERAGE_FILES = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Signal/Signal-Prefix.pch"; + GCC_VERSION = ""; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = NO; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + HEADER_SEARCH_PATHS = ( + "${PODS_HEADERS_SEARCH_PATHS}", + "$(inherited)", + "\"${SRCROOT}/Signal/lib/speex/include\"", + "\"${SRCROOT}/Signal/lib/ogg/include\"", + "\"${SRCROOT}/Signal/lib/debug/include\"", + "\"$(SRCROOT)/libtommath\"", + "\"$(SRCROOT)/libtomcrypt/headers\"", + "\"$(SRCROOT)/spandsp/spandsp/spandsp\"", + "\"$(SRCROOT)/Libraries\"/**", + "\"$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources\"", + ); + INFOPLIST_FILE = "Signal/test/Supporting Files/SignalTests-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)", + ); + OTHER_LDFLAGS = ( + "-all_load", + "-ObjC", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.whispersystems.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = SignalTests; + PROVISIONING_PROFILE = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Signal/test/SignalTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Signal.app/Signal"; + VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64"; + }; + name = Test; + }; D221A0BA169C9E5F00537ABF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2776,6 +2979,7 @@ isa = XCConfigurationList; buildConfigurations = ( D221A0BA169C9E5F00537ABF /* Debug */, + 451DA3CC1F152887008E2423 /* Test */, D221A0BB169C9E5F00537ABF /* App Store Release */, ); defaultConfigurationIsVisible = 0; @@ -2785,6 +2989,7 @@ isa = XCConfigurationList; buildConfigurations = ( D221A0BD169C9E5F00537ABF /* Debug */, + 451DA3CD1F152887008E2423 /* Test */, D221A0BE169C9E5F00537ABF /* App Store Release */, ); defaultConfigurationIsVisible = 0; @@ -2794,6 +2999,7 @@ isa = XCConfigurationList; buildConfigurations = ( D221A0C0169C9E5F00537ABF /* Debug */, + 451DA3CE1F152887008E2423 /* Test */, D221A0C1169C9E5F00537ABF /* App Store Release */, ); defaultConfigurationIsVisible = 0; diff --git a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme index c74cfaba0..f21a4537c 100644 --- a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme +++ b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme @@ -28,7 +28,7 @@ buildForAnalyzing = "YES"> @@ -37,7 +37,7 @@ diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index ad38b4392..b59c9cac9 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -4,6 +4,7 @@ #import +#import "TSMessageAdapter.h" #import "AttachmentSharing.h" #import "Environment.h" #import "FLAnimatedImage.h" diff --git a/Signal/test/Models/AccountManagerTest.swift b/Signal/test/Models/AccountManagerTest.swift index 5fbd8750f..2458a6cbe 100644 --- a/Signal/test/Models/AccountManagerTest.swift +++ b/Signal/test/Models/AccountManagerTest.swift @@ -42,7 +42,7 @@ class TokenObtainingTSAccountManager: VerifyingTSAccountManager { class AccountManagerTest: XCTestCase { - let tsAccountManager = FailingTSAccountManager() + let tsAccountManager = FailingTSAccountManager(networkManager: TSNetworkManager.sharedManager() as! TSNetworkManager, storageManager: TSStorageManager.shared()) func testRegisterWhenEmptyCode() { let accountManager = AccountManager(textSecureAccountManager: tsAccountManager) @@ -86,7 +86,8 @@ class AccountManagerTest: XCTestCase { } func testSuccessfulRegistration() { - let tsAccountManager = TokenObtainingTSAccountManager() + let tsAccountManager = TokenObtainingTSAccountManager(networkManager: TSNetworkManager.sharedManager() as! TSNetworkManager, storageManager: TSStorageManager.shared()) + let accountManager = AccountManager(textSecureAccountManager: tsAccountManager) let expectation = self.expectation(description: "should succeed") diff --git a/Signal/test/Models/MesssagesBubblesSizeCalculatorTest.swift b/Signal/test/Models/MesssagesBubblesSizeCalculatorTest.swift index 7bb7a8dcf..130d29c99 100644 --- a/Signal/test/Models/MesssagesBubblesSizeCalculatorTest.swift +++ b/Signal/test/Models/MesssagesBubblesSizeCalculatorTest.swift @@ -1,39 +1,9 @@ -// Created by Michael Kirk on 11/2/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// import XCTest -class FakeMessageData: NSObject, JSQMessageData { - public func senderId() -> String! { - return "fake-sender-id" - } - - func senderDisplayName() -> String! { - return "fake-senderDisplayName" - } - - func date() -> Date! { - return Date() - } - - @objc func isMediaMessage() -> Bool { - return false - } - - @objc func messageHash() -> UInt { - return 1 - } - - var bodyText: String? = "fake message data text" - func text() -> String? { - return self.bodyText - } - - init(text: String?) { - self.bodyText = text; - } -} - class FakeiPhone6JSQMessagesCollectionViewFlowLayout: JSQMessagesCollectionViewFlowLayout { // This value was nabbed by inspecting the super class layout.itemSize while debugging the `messageBubbleSizeForMessageData`. // It requires the view to actually be rendered to get a proper size, so we're baking it in here. @@ -44,81 +14,94 @@ class FakeiPhone6JSQMessagesCollectionViewFlowLayout: JSQMessagesCollectionViewF /** * This is a brittle test, which will break if our layout changes. It serves mostly as documentation for cases to * consider when changing the bubble size calculator. Primarly these test cases came out of a bug introduced in iOS10, - * which prevents us from computing proper boudning box for text that uses the UIEmoji font. + * which prevents us from computing proper bounding box for text that uses the UIEmoji font. * * If one of these tests breaks, it should be OK to update the expected value so long as you've tested the result renders - * correctly in the running app (the reference sizes ewre computed in the context of an iphone6 layour. + * correctly in the running app (the reference sizes were computed in the context of an iphone6 layout. * @see `FakeiPhone6JSQMessagesCollectionViewFlowLayout` */ class MesssagesBubblesSizeCalculatorTest: XCTestCase { - + let indexPath = IndexPath() let layout = FakeiPhone6JSQMessagesCollectionViewFlowLayout() let calculator = MessagesBubblesSizeCalculator() + let thread = TSContactThread()! + let contactsManager = OWSContactsManager() + + func messageDataForForText(_ text: String?) -> JSQMessageData { + let interaction = TSOutgoingMessage(timestamp: 0, in: thread, messageBody: text) + interaction.save() + return TSMessageAdapter.messageViewData(with: interaction, in: thread, contactsManager: self.contactsManager) + } func testHeightForNilMessage() { - let messageData = FakeMessageData(text:nil) + let text: String? = nil + let messageData = self.messageDataForForText(text) let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(16, actual.height); + XCTAssertEqual(37, actual.height) } func testHeightForShort1LineMessage() { - let messageData = FakeMessageData(text:"foo") + let text = "foo" + let messageData = self.messageDataForForText(text) let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(38, actual.height); + XCTAssertEqual(38, actual.height) } func testHeightForLong1LineMessage() { - let messageData = FakeMessageData(text:"1 2 3 4 5 6 7 8 9 10 11 12 13 14 x") + let text = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 x" + let messageData = self.messageDataForForText(text) let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(38, actual.height); + XCTAssertEqual(38, actual.height) } func testHeightForShort2LineMessage() { - let messageData = FakeMessageData(text:"1 2 3 4 5 6 7 8 9 10 11 12 13 14 x 1") + let text = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 x 1" + let messageData = self.messageDataForForText(text) let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(59, actual.height); + XCTAssertEqual(59, actual.height) } func testHeightForLong2LineMessage() { - let messageData = FakeMessageData(text:"1 2 3 4 5 6 7 8 9 10 11 12 13 14 x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 x") + let text = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 x" + let messageData = self.messageDataForForText(text) let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(59, actual.height); + XCTAssertEqual(59, actual.height) } func testHeightForiOS10EmojiBug() { - let messageData = FakeMessageData(text:"Wunderschönen Guten Morgaaaahhhn 😝 - hast du gut geschlafen ☺️😘") + let messageData = self.messageDataForForText("Wunderschönen Guten Morgaaaahhhn 😝 - hast du gut geschlafen ☺️😘") let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(85.5, actual.height); + XCTAssertEqual(85.5, actual.height) } func testHeightForiOS10EmojiBug2() { - let messageData = FakeMessageData(text:"Test test test test test test test test test test test test 😊❤️❤️") + let messageData = self.messageDataForForText("Test test test test test test test test test test test test 😊❤️❤️") let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) - XCTAssertEqual(62, actual.height); + XCTAssertEqual(62, actual.height) } func testHeightForChineseWithEmojiBug() { - let messageData = FakeMessageData(text:"一二三四五六七八九十甲乙丙😝戊己庚辛壬圭咖啡牛奶餅乾水果蛋糕") + let messageData = self.messageDataForForText("一二三四五六七八九十甲乙丙😝戊己庚辛壬圭咖啡牛奶餅乾水果蛋糕") let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) // erroneously seeing 69 with the emoji fix in place. - XCTAssertEqual(85.5, actual.height); + XCTAssertEqual(85.5, actual.height) } func testHeightForChineseWithoutEmojiBug() { - let messageData = FakeMessageData(text:"一二三四五六七八九十甲乙丙丁戊己庚辛壬圭咖啡牛奶餅乾水果蛋糕") + let messageData = self.messageDataForForText("一二三四五六七八九十甲乙丙丁戊己庚辛壬圭咖啡牛奶餅乾水果蛋糕") let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) // erroneously seeing 69 with the emoji fix in place. - XCTAssertEqual(81, actual.height); + XCTAssertEqual(81, actual.height) } func testHeightForiOS10DoubleSpaceNumbersBug() { - let messageData = FakeMessageData(text:"12345678901234567890") + let messageData = self.messageDataForForText("12345678901234567890") let actual = calculator.messageBubbleSize(for: messageData, at: indexPath, with: layout) // erroneously seeing 51 with emoji fix in place. It's the call to "fix string" - XCTAssertEqual(59, actual.height); + XCTAssertEqual(59, actual.height) } } diff --git a/Signal/test/ViewControllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m b/Signal/test/ViewControllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m index 6d91be59c..4cf143938 100644 --- a/Signal/test/ViewControllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m +++ b/Signal/test/ViewControllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m @@ -101,7 +101,9 @@ - (void)testCanPerformEditingActionWithVideoMessage { - TSAttachmentStream *videoAttachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" filename:nil]; + TSAttachmentStream *videoAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" sourceFilename:nil]; + self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:videoAttachment incoming:NO]; XCTAssertTrue([self.messageAdapter canPerformEditingAction:@selector(delete:)]); @@ -114,7 +116,8 @@ - (void)testCanPerformEditingActionWithAudioMessage { - TSAttachmentStream *audioAttachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" filename:nil]; + TSAttachmentStream *audioAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:nil]; self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:audioAttachment incoming:NO]; XCTAssertTrue([self.messageAdapter canPerformEditingAction:@selector(delete:)]); @@ -161,7 +164,8 @@ XCTAssertNotNil([TSMessage fetchObjectWithUniqueID:self.message.uniqueId]); NSError *error; - TSAttachmentStream *videoAttachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" filename:nil]; + TSAttachmentStream *videoAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" sourceFilename:nil]; [videoAttachment writeData:[NSData new] error:&error]; [videoAttachment save]; @@ -183,7 +187,8 @@ XCTAssertNotNil([TSMessage fetchObjectWithUniqueID:self.message.uniqueId]); NSError *error; - TSAttachmentStream *audioAttachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" filename:nil]; + TSAttachmentStream *audioAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:nil]; [audioAttachment writeData:[NSData new] error:&error]; [audioAttachment save]; @@ -217,7 +222,7 @@ XCTAssertNil(UIPasteboard.generalPasteboard.image); NSError *error; - TSAttachmentStream *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" filename:nil]; + TSAttachmentStream *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil]; [attachment writeData:self.fakeAudioData error:&error]; [attachment save]; @@ -245,7 +250,8 @@ UIPasteboard.generalPasteboard.items = @[]; NSError *error; - TSAttachmentStream *videoAttachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" filename:nil]; + TSAttachmentStream *videoAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" sourceFilename:nil]; [videoAttachment writeData:self.fakeVideoData error:&error]; self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:videoAttachment incoming:YES]; @@ -261,7 +267,8 @@ XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMP3]); NSError *error; - TSAttachmentStream *audioAttachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" filename:nil]; + TSAttachmentStream *audioAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:nil]; [audioAttachment writeData:self.fakeAudioData error:&error]; self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:audioAttachment incoming:NO]; @@ -275,7 +282,8 @@ XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeMPEG4Audio]); NSError *error; - TSAttachmentStream *audioAttachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/x-m4a" filename:nil]; + TSAttachmentStream *audioAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"audio/x-m4a" sourceFilename:nil]; [audioAttachment writeData:self.fakeAudioData error:&error]; self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:audioAttachment incoming:NO]; @@ -289,7 +297,8 @@ XCTAssertNil([UIPasteboard.generalPasteboard dataForPasteboardType:(NSString *)kUTTypeAudio]); NSError *error; - TSAttachmentStream *audioAttachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/wav" filename:nil]; + TSAttachmentStream *audioAttachment = + [[TSAttachmentStream alloc] initWithContentType:@"audio/wav" sourceFilename:nil]; [audioAttachment writeData:self.fakeAudioData error:&error]; self.messageAdapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:audioAttachment incoming:NO]; diff --git a/Signal/test/contact/ContactsPickerTest.swift b/Signal/test/contact/ContactsPickerTest.swift index f8f1d9d0e..394620d29 100644 --- a/Signal/test/contact/ContactsPickerTest.swift +++ b/Signal/test/contact/ContactsPickerTest.swift @@ -1,88 +1,84 @@ // -// ContactsPickerTest.swift -// Signal -// -// Created by Daniel Rosado on 03/12/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // import XCTest @testable import Signal +import Contacts final class ContactsPickerTest: XCTestCase { private var prevLang: Any? - + override func setUp() { super.setUp() - + prevLang = getLang() } - + override func tearDown() { super.tearDown() - + if let prevLang = prevLang { setLang(value: prevLang) } } - + @available(iOS 9.0, *) func testContactSectionMatchesEmailFirstLetterWhenOnlyEmailContact() { setLangEN() - + let emailOnlyContactB = CNMutableContact() emailOnlyContactB.emailAddresses.append(CNLabeledValue(label: nil, value: "bla@bla.com")) - + let emailOnlyContactD = CNMutableContact() emailOnlyContactD.emailAddresses.append(CNLabeledValue(label: nil, value: "dude@bla.com")) - + let contactsPicker = ContactsPicker(delegate: nil) let collatedContacts = contactsPicker.collatedContacts([emailOnlyContactB, emailOnlyContactD]) - + let sectionTitles = contactsPicker.collation.sectionTitles if let bIndex = sectionTitles.index(of: "B") { let bSectionContacts = collatedContacts[bIndex] XCTAssertEqual(bSectionContacts.first, emailOnlyContactB) } - + if let dIndex = sectionTitles.index(of: "D") { let dSectionContacts = collatedContacts[dIndex] XCTAssertEqual(dSectionContacts.first, emailOnlyContactD) } } - + @available(iOS 9.0, *) func testContactSectionMatchesNameFirstLetterWhenNameExistsInContact() { setLangEN() - + let nameAndEmailContact = CNMutableContact() nameAndEmailContact.givenName = "Alice" nameAndEmailContact.emailAddresses.append(CNLabeledValue(label: nil, value: "nameAndEmail@bla.com")) - + let contactsPicker = ContactsPicker(delegate: nil) - let collatedContacts = contactsPicker.collatedContacts([nameAndEmailContact]) - + let collatedContacts = contactsPicker.collatedContacts([nameAndEmailContact]) + let sectionTitles = contactsPicker.collation.sectionTitles if let aIndex = sectionTitles.index(of: "A") { let aSectionContacts = collatedContacts[aIndex] XCTAssertEqual(aSectionContacts.first, nameAndEmailContact) } } - - + private func setLangEN() { setLang(value: "en") } - + private func setLang(value: Any) { UserDefaults.standard.set(value, forKey: "AppleLanguages") UserDefaults.standard.synchronize() } - + private func setLang(value: String) { setLang(value: [value]) } - + private func getLang() -> Any? { return UserDefaults.standard.value(forKey: "AppleLanguages") } diff --git a/fastlane/.gitignore b/fastlane/.gitignore new file mode 100644 index 000000000..007b73ee6 --- /dev/null +++ b/fastlane/.gitignore @@ -0,0 +1 @@ +test_output diff --git a/fastlane/Scanfile b/fastlane/Scanfile new file mode 100644 index 000000000..a58da5440 --- /dev/null +++ b/fastlane/Scanfile @@ -0,0 +1,7 @@ +# For more information about this configuration visit +# https://github.com/fastlane/fastlane/tree/master/scan#scanfile + +workspace "Signal.xcworkspace" +scheme "Signal" +devices ["iPhone SE"] +