├── .gitignore ├── .travis.yml ├── Chirp.podspec ├── Example ├── Chirp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Chirp-Example.xcscheme ├── Chirp.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Chirp │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── Chirp.podspec.json │ ├── Manifest.lock │ ├── Nimble │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Nimble │ │ │ ├── Adapters │ │ │ │ ├── AdapterProtocols.swift │ │ │ │ ├── AssertionDispatcher.swift │ │ │ │ ├── AssertionRecorder.swift │ │ │ │ ├── NMBExpectation.swift │ │ │ │ ├── NMBObjCMatcher.swift │ │ │ │ ├── NimbleEnvironment.swift │ │ │ │ └── NimbleXCTestHandler.swift │ │ │ ├── DSL+Wait.swift │ │ │ ├── DSL.swift │ │ │ ├── Expectation.swift │ │ │ ├── ExpectationMessage.swift │ │ │ ├── Expression.swift │ │ │ ├── FailureMessage.swift │ │ │ ├── Matchers │ │ │ │ ├── AllPass.swift │ │ │ │ ├── Async.swift │ │ │ │ ├── BeAKindOf.swift │ │ │ │ ├── BeAnInstanceOf.swift │ │ │ │ ├── BeCloseTo.swift │ │ │ │ ├── BeEmpty.swift │ │ │ │ ├── BeGreaterThan.swift │ │ │ │ ├── BeGreaterThanOrEqualTo.swift │ │ │ │ ├── BeIdenticalTo.swift │ │ │ │ ├── BeLessThan.swift │ │ │ │ ├── BeLessThanOrEqual.swift │ │ │ │ ├── BeLogical.swift │ │ │ │ ├── BeNil.swift │ │ │ │ ├── BeVoid.swift │ │ │ │ ├── BeginWith.swift │ │ │ │ ├── Contain.swift │ │ │ │ ├── ContainElementSatisfying.swift │ │ │ │ ├── ElementsEqual.swift │ │ │ │ ├── EndWith.swift │ │ │ │ ├── Equal.swift │ │ │ │ ├── HaveCount.swift │ │ │ │ ├── Match.swift │ │ │ │ ├── MatchError.swift │ │ │ │ ├── MatcherFunc.swift │ │ │ │ ├── MatcherProtocols.swift │ │ │ │ ├── PostNotification.swift │ │ │ │ ├── Predicate.swift │ │ │ │ ├── RaisesException.swift │ │ │ │ ├── SatisfyAllOf.swift │ │ │ │ ├── SatisfyAnyOf.swift │ │ │ │ ├── ThrowAssertion.swift │ │ │ │ ├── ThrowError.swift │ │ │ │ └── ToSucceed.swift │ │ │ ├── Nimble.h │ │ │ └── Utils │ │ │ │ ├── Await.swift │ │ │ │ ├── Errors.swift │ │ │ │ ├── Functional.swift │ │ │ │ ├── SourceLocation.swift │ │ │ │ └── Stringers.swift │ │ │ └── NimbleObjectiveC │ │ │ ├── DSL.h │ │ │ ├── DSL.m │ │ │ ├── NMBExceptionCapture.h │ │ │ ├── NMBExceptionCapture.m │ │ │ ├── NMBStringify.h │ │ │ ├── NMBStringify.m │ │ │ └── XCTestObservationCenter+Register.m │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── Quick │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Quick │ │ │ ├── Behavior.swift │ │ │ ├── Callsite.swift │ │ │ ├── Configuration │ │ │ │ └── Configuration.swift │ │ │ ├── DSL │ │ │ │ ├── DSL.swift │ │ │ │ └── World+DSL.swift │ │ │ ├── ErrorUtility.swift │ │ │ ├── Example.swift │ │ │ ├── ExampleGroup.swift │ │ │ ├── ExampleMetadata.swift │ │ │ ├── Filter.swift │ │ │ ├── Hooks │ │ │ │ ├── Closures.swift │ │ │ │ ├── ExampleHooks.swift │ │ │ │ ├── HooksPhase.swift │ │ │ │ └── SuiteHooks.swift │ │ │ ├── NSBundle+CurrentTestBundle.swift │ │ │ ├── QuickSelectedTestSuiteBuilder.swift │ │ │ ├── QuickTestSuite.swift │ │ │ ├── String+C99ExtendedIdentifier.swift │ │ │ ├── URL+FileName.swift │ │ │ └── World.swift │ │ │ ├── QuickObjectiveC │ │ │ ├── Configuration │ │ │ │ ├── QuickConfiguration.h │ │ │ │ └── QuickConfiguration.m │ │ │ ├── DSL │ │ │ │ ├── QCKDSL.h │ │ │ │ └── QCKDSL.m │ │ │ ├── Quick.h │ │ │ ├── QuickSpec.h │ │ │ ├── QuickSpec.m │ │ │ └── XCTestSuite+QuickTestSuiteBuilder.m │ │ │ └── QuickSpecBase │ │ │ ├── QuickSpecBase.m │ │ │ └── include │ │ │ └── QuickSpecBase.h │ └── Target Support Files │ │ ├── Chirp │ │ ├── Chirp-Info.plist │ │ ├── Chirp-dummy.m │ │ ├── Chirp-prefix.pch │ │ ├── Chirp-umbrella.h │ │ ├── Chirp.modulemap │ │ ├── Chirp.xcconfig │ │ ├── Info.plist │ │ ├── ResourceBundle-Chirp-Chirp-Info.plist │ │ └── ResourceBundle-Chirp-Info.plist │ │ ├── Nimble │ │ ├── Info.plist │ │ ├── Nimble-Info.plist │ │ ├── Nimble-dummy.m │ │ ├── Nimble-prefix.pch │ │ ├── Nimble-umbrella.h │ │ ├── Nimble.modulemap │ │ └── Nimble.xcconfig │ │ ├── Pods-Chirp_Example │ │ ├── Info.plist │ │ ├── Pods-Chirp_Example-Info.plist │ │ ├── Pods-Chirp_Example-acknowledgements.markdown │ │ ├── Pods-Chirp_Example-acknowledgements.plist │ │ ├── Pods-Chirp_Example-dummy.m │ │ ├── Pods-Chirp_Example-frameworks.sh │ │ ├── Pods-Chirp_Example-resources.sh │ │ ├── Pods-Chirp_Example-umbrella.h │ │ ├── Pods-Chirp_Example.debug.xcconfig │ │ ├── Pods-Chirp_Example.modulemap │ │ └── Pods-Chirp_Example.release.xcconfig │ │ ├── Pods-Chirp_Tests │ │ ├── Info.plist │ │ ├── Pods-Chirp_Tests-Info.plist │ │ ├── Pods-Chirp_Tests-acknowledgements.markdown │ │ ├── Pods-Chirp_Tests-acknowledgements.plist │ │ ├── Pods-Chirp_Tests-dummy.m │ │ ├── Pods-Chirp_Tests-frameworks.sh │ │ ├── Pods-Chirp_Tests-resources.sh │ │ ├── Pods-Chirp_Tests-umbrella.h │ │ ├── Pods-Chirp_Tests.debug.xcconfig │ │ ├── Pods-Chirp_Tests.modulemap │ │ └── Pods-Chirp_Tests.release.xcconfig │ │ └── Quick │ │ ├── Info.plist │ │ ├── Quick-Info.plist │ │ ├── Quick-dummy.m │ │ ├── Quick-prefix.pch │ │ ├── Quick-umbrella.h │ │ ├── Quick.modulemap │ │ └── Quick.xcconfig └── Tests │ ├── Info.plist │ ├── Tests.swift │ └── test.mp3 ├── LICENSE ├── Pod ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ └── Chirp.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | # Pods/ 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | language: objective-c 6 | # cache: cocoapods 7 | # podfile: Example/Podfile 8 | # before_install: 9 | # - gem install cocoapods # Since Travis is not always on latest version 10 | # - pod install --project-directory=Example 11 | script: 12 | - set -o pipefail && xcodebuild test -workspace Example/Chirp.xcworkspace -scheme Chirp-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty 13 | - pod lib lint 14 | -------------------------------------------------------------------------------- /Chirp.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint Chirp.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = "Chirp" 11 | s.version = "1.2.0" 12 | s.summary = "The easiest way to prepare, play, and remove sounds in your Swift app!" 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | s.description = <<-DESC 20 | Bored of manually managing SystemSoundIDs? Chirp gives you a quick and easy way to prepare, play, and remove sounds in your app! Each of those only taking 1 line of code. 21 | DESC 22 | 23 | s.homepage = "https://github.com/trifl/Chirp" 24 | # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" 25 | s.license = 'MIT' 26 | s.author = { "JP McGlone" => "jp@trifl.co" } 27 | s.source = { :git => "https://github.com/trifl/Chirp.git", :tag => s.version.to_s } 28 | # s.social_media_url = 'https://twitter.com/' 29 | 30 | s.platform = :ios, '8.0' 31 | s.requires_arc = true 32 | 33 | s.source_files = 'Pod/Classes/**/*' 34 | # s.resource_bundles = { 35 | # 'Chirp' => ['Pod/Assets/*.png'] 36 | # } 37 | 38 | # s.public_header_files = 'Pod/Classes/**/*.h' 39 | # s.frameworks = 'UIKit', 'MapKit' 40 | # s.dependency 'AFNetworking', '~> 2.3' 41 | end 42 | -------------------------------------------------------------------------------- /Example/Chirp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Chirp.xcodeproj/xcshareddata/xcschemes/Chirp-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/Chirp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Chirp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Chirp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain 4 | class AppDelegate: UIResponder, UIApplicationDelegate { 5 | 6 | var window: UIWindow? 7 | 8 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 9 | // Override point for customization after application launch. 10 | return true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Example/Chirp/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/Chirp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/Chirp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/Chirp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/Chirp/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class ViewController: UIViewController { 4 | override func viewDidLoad() { 5 | super.viewDidLoad() 6 | // Do any additional setup after loading the view, typically from a nib. 7 | } 8 | 9 | override func didReceiveMemoryWarning() { 10 | super.didReceiveMemoryWarning() 11 | // Dispose of any resources that can be recreated. 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | use_frameworks! 3 | platform :ios, '11.0' 4 | 5 | target 'Chirp_Example' do 6 | pod "Chirp", :path => "../" 7 | end 8 | 9 | target 'Chirp_Tests' do 10 | pod "Chirp", :path => "../" 11 | 12 | pod 'Quick' 13 | pod 'Nimble' 14 | end 15 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Chirp (1.1.1) 3 | - Nimble (8.0.1) 4 | - Quick (2.1.0) 5 | 6 | DEPENDENCIES: 7 | - Chirp (from `../`) 8 | - Nimble 9 | - Quick 10 | 11 | SPEC REPOS: 12 | https://github.com/cocoapods/specs.git: 13 | - Nimble 14 | - Quick 15 | 16 | EXTERNAL SOURCES: 17 | Chirp: 18 | :path: "../" 19 | 20 | SPEC CHECKSUMS: 21 | Chirp: e06920df90dd33b3e74c988c58f621a8a1e41e7d 22 | Nimble: 45f786ae66faa9a709624227fae502db55a8bdd0 23 | Quick: 4be43f6634acfa727dd106bdf3929ce125ffa79d 24 | 25 | PODFILE CHECKSUM: 5a87d3d4659f3d1a40d3397ed7655b016dea8724 26 | 27 | COCOAPODS: 1.7.0 28 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/Chirp.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Chirp", 3 | "version": "1.1.1", 4 | "summary": "The easiest way to prepare, play, and remove sounds in your Swift app!", 5 | "description": "Bored of manually managing SystemSoundIDs? Chirp gives you a quick and easy way to prepare, play, and remove sounds in your app! Each of those only taking 1 line of code.", 6 | "homepage": "https://github.com/trifl/Chirp", 7 | "license": "MIT", 8 | "authors": { 9 | "JP McGlone": "jp@trifl.co" 10 | }, 11 | "source": { 12 | "git": "https://github.com/trifl/Chirp.git", 13 | "tag": "1.1.1" 14 | }, 15 | "platforms": { 16 | "ios": "8.0" 17 | }, 18 | "requires_arc": true, 19 | "source_files": "Pod/Classes/**/*", 20 | "resource_bundles": { 21 | "Chirp": [ 22 | "Pod/Assets/*.png" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Chirp (1.1.1) 3 | - Nimble (8.0.1) 4 | - Quick (2.1.0) 5 | 6 | DEPENDENCIES: 7 | - Chirp (from `../`) 8 | - Nimble 9 | - Quick 10 | 11 | SPEC REPOS: 12 | https://github.com/cocoapods/specs.git: 13 | - Nimble 14 | - Quick 15 | 16 | EXTERNAL SOURCES: 17 | Chirp: 18 | :path: "../" 19 | 20 | SPEC CHECKSUMS: 21 | Chirp: e06920df90dd33b3e74c988c58f621a8a1e41e7d 22 | Nimble: 45f786ae66faa9a709624227fae502db55a8bdd0 23 | Quick: 4be43f6634acfa727dd106bdf3929ce125ffa79d 24 | 25 | PODFILE CHECKSUM: 5a87d3d4659f3d1a40d3397ed7655b016dea8724 26 | 27 | COCOAPODS: 1.7.0 28 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Protocol for the assertion handler that Nimble uses for all expectations. 4 | public protocol AssertionHandler { 5 | func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) 6 | } 7 | 8 | /// Global backing interface for assertions that Nimble creates. 9 | /// Defaults to a private test handler that passes through to XCTest. 10 | /// 11 | /// If XCTest is not available, you must assign your own assertion handler 12 | /// before using any matchers, otherwise Nimble will abort the program. 13 | /// 14 | /// @see AssertionHandler 15 | public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in 16 | // swiftlint:disable:previous identifier_name 17 | return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler() 18 | }() 19 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift: -------------------------------------------------------------------------------- 1 | /// AssertionDispatcher allows multiple AssertionHandlers to receive 2 | /// assertion messages. 3 | /// 4 | /// @warning Does not fully dispatch if one of the handlers raises an exception. 5 | /// This is possible with XCTest-based assertion handlers. 6 | /// 7 | public class AssertionDispatcher: AssertionHandler { 8 | let handlers: [AssertionHandler] 9 | 10 | public init(handlers: [AssertionHandler]) { 11 | self.handlers = handlers 12 | } 13 | 14 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 15 | for handler in handlers { 16 | handler.assert(assertion, message: message, location: location) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A data structure that stores information about an assertion when 4 | /// AssertionRecorder is set as the Nimble assertion handler. 5 | /// 6 | /// @see AssertionRecorder 7 | /// @see AssertionHandler 8 | public struct AssertionRecord: CustomStringConvertible { 9 | /// Whether the assertion succeeded or failed 10 | public let success: Bool 11 | /// The failure message the assertion would display on failure. 12 | public let message: FailureMessage 13 | /// The source location the expectation occurred on. 14 | public let location: SourceLocation 15 | 16 | public var description: String { 17 | return "AssertionRecord { success=\(success), message='\(message.stringValue)', location=\(location) }" 18 | } 19 | } 20 | 21 | /// An AssertionHandler that silently records assertions that Nimble makes. 22 | /// This is useful for testing failure messages for matchers. 23 | /// 24 | /// @see AssertionHandler 25 | public class AssertionRecorder: AssertionHandler { 26 | /// All the assertions that were captured by this recorder 27 | public var assertions = [AssertionRecord]() 28 | 29 | public init() {} 30 | 31 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 32 | assertions.append( 33 | AssertionRecord( 34 | success: assertion, 35 | message: message, 36 | location: location)) 37 | } 38 | } 39 | 40 | extension NMBExceptionCapture { 41 | internal func tryBlockThrows(_ unsafeBlock: () throws -> Void) throws { 42 | var catchedError: Error? 43 | tryBlock { 44 | do { 45 | try unsafeBlock() 46 | } catch { 47 | catchedError = error 48 | } 49 | } 50 | if let error = catchedError { 51 | throw error 52 | } 53 | } 54 | } 55 | 56 | /// Allows you to temporarily replace the current Nimble assertion handler with 57 | /// the one provided for the scope of the closure. 58 | /// 59 | /// Once the closure finishes, then the original Nimble assertion handler is restored. 60 | /// 61 | /// @see AssertionHandler 62 | public func withAssertionHandler(_ tempAssertionHandler: AssertionHandler, 63 | file: FileString = #file, 64 | line: UInt = #line, 65 | closure: () throws -> Void) { 66 | let environment = NimbleEnvironment.activeInstance 67 | let oldRecorder = environment.assertionHandler 68 | let capturer = NMBExceptionCapture(handler: nil, finally: ({ 69 | environment.assertionHandler = oldRecorder 70 | })) 71 | environment.assertionHandler = tempAssertionHandler 72 | 73 | do { 74 | try capturer.tryBlockThrows { 75 | try closure() 76 | } 77 | } catch { 78 | let failureMessage = FailureMessage() 79 | failureMessage.stringValue = "unexpected error thrown: <\(error)>" 80 | let location = SourceLocation(file: file, line: line) 81 | tempAssertionHandler.assert(false, message: failureMessage, location: location) 82 | } 83 | } 84 | 85 | /// Captures expectations that occur in the given closure. Note that all 86 | /// expectations will still go through to the default Nimble handler. 87 | /// 88 | /// This can be useful if you want to gather information about expectations 89 | /// that occur within a closure. 90 | /// 91 | /// @param silently expectations are no longer send to the default Nimble 92 | /// assertion handler when this is true. Defaults to false. 93 | /// 94 | /// @see gatherFailingExpectations 95 | public func gatherExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] { 96 | let previousRecorder = NimbleEnvironment.activeInstance.assertionHandler 97 | let recorder = AssertionRecorder() 98 | let handlers: [AssertionHandler] 99 | 100 | if silently { 101 | handlers = [recorder] 102 | } else { 103 | handlers = [recorder, previousRecorder] 104 | } 105 | 106 | let dispatcher = AssertionDispatcher(handlers: handlers) 107 | withAssertionHandler(dispatcher, closure: closure) 108 | return recorder.assertions 109 | } 110 | 111 | /// Captures failed expectations that occur in the given closure. Note that all 112 | /// expectations will still go through to the default Nimble handler. 113 | /// 114 | /// This can be useful if you want to gather information about failed 115 | /// expectations that occur within a closure. 116 | /// 117 | /// @param silently expectations are no longer send to the default Nimble 118 | /// assertion handler when this is true. Defaults to false. 119 | /// 120 | /// @see gatherExpectations 121 | /// @see raiseException source for an example use case. 122 | public func gatherFailingExpectations(silently: Bool = false, closure: () -> Void) -> [AssertionRecord] { 123 | let assertions = gatherExpectations(silently: silently, closure: closure) 124 | return assertions.filter { assertion in 125 | !assertion.success 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) 4 | 5 | // swiftlint:disable line_length 6 | public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) throws -> Bool 7 | public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool 8 | // swiftlint:enable line_length 9 | 10 | public class NMBObjCMatcher: NSObject, NMBMatcher { 11 | // swiftlint:disable identifier_name 12 | let _match: MatcherBlock 13 | let _doesNotMatch: MatcherBlock 14 | // swiftlint:enable identifier_name 15 | let canMatchNil: Bool 16 | 17 | public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) { 18 | self.canMatchNil = canMatchNil 19 | self._match = matcher 20 | self._doesNotMatch = notMatcher 21 | } 22 | 23 | public convenience init(matcher: @escaping MatcherBlock) { 24 | self.init(canMatchNil: true, matcher: matcher) 25 | } 26 | 27 | public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) { 28 | self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in 29 | return try !matcher(actualExpression, failureMessage) 30 | })) 31 | } 32 | 33 | public convenience init(matcher: @escaping FullMatcherBlock) { 34 | self.init(canMatchNil: true, matcher: matcher) 35 | } 36 | 37 | public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) { 38 | self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in 39 | return try matcher(actualExpression, failureMessage, false) 40 | }), notMatcher: ({ actualExpression, failureMessage in 41 | return try matcher(actualExpression, failureMessage, true) 42 | })) 43 | } 44 | 45 | private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool { 46 | do { 47 | if !canMatchNil { 48 | if try actualExpression.evaluate() == nil { 49 | failureMessage.postfixActual = " (use beNil() to match nils)" 50 | return false 51 | } 52 | } 53 | } catch let error { 54 | failureMessage.actualValue = "an unexpected error thrown: \(error)" 55 | return false 56 | } 57 | return true 58 | } 59 | 60 | public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { 61 | let expr = Expression(expression: actualBlock, location: location) 62 | let result: Bool 63 | do { 64 | result = try _match(expr, failureMessage) 65 | } catch let error { 66 | failureMessage.stringValue = "unexpected error thrown: <\(error)>" 67 | return false 68 | } 69 | 70 | if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { 71 | return result 72 | } else { 73 | return false 74 | } 75 | } 76 | 77 | public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool { 78 | let expr = Expression(expression: actualBlock, location: location) 79 | let result: Bool 80 | do { 81 | result = try _doesNotMatch(expr, failureMessage) 82 | } catch let error { 83 | failureMessage.stringValue = "unexpected error thrown: <\(error)>" 84 | return false 85 | } 86 | 87 | if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) { 88 | return result 89 | } else { 90 | return false 91 | } 92 | } 93 | } 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift: -------------------------------------------------------------------------------- 1 | import Dispatch 2 | import Foundation 3 | 4 | /// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this 5 | /// class' existence 6 | internal class NimbleEnvironment: NSObject { 7 | static var activeInstance: NimbleEnvironment { 8 | get { 9 | let env = Thread.current.threadDictionary["NimbleEnvironment"] 10 | if let env = env as? NimbleEnvironment { 11 | return env 12 | } else { 13 | let newEnv = NimbleEnvironment() 14 | self.activeInstance = newEnv 15 | return newEnv 16 | } 17 | } 18 | set { 19 | Thread.current.threadDictionary["NimbleEnvironment"] = newValue 20 | } 21 | } 22 | 23 | // swiftlint:disable:next todo 24 | // TODO: eventually migrate the global to this environment value 25 | var assertionHandler: AssertionHandler { 26 | get { return NimbleAssertionHandler } 27 | set { NimbleAssertionHandler = newValue } 28 | } 29 | 30 | var suppressTVOSAssertionWarning: Bool = false 31 | var awaiter: Awaiter 32 | 33 | override init() { 34 | let timeoutQueue = DispatchQueue.global(qos: .userInitiated) 35 | awaiter = Awaiter( 36 | waitLock: AssertionWaitLock(), 37 | asyncQueue: .main, 38 | timeoutQueue: timeoutQueue 39 | ) 40 | 41 | super.init() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XCTest 3 | 4 | /// Default handler for Nimble. This assertion handler passes failures along to 5 | /// XCTest. 6 | public class NimbleXCTestHandler: AssertionHandler { 7 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 8 | if !assertion { 9 | recordFailure("\(message.stringValue)\n", location: location) 10 | } 11 | } 12 | } 13 | 14 | /// Alternative handler for Nimble. This assertion handler passes failures along 15 | /// to XCTest by attempting to reduce the failure message size. 16 | public class NimbleShortXCTestHandler: AssertionHandler { 17 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 18 | if !assertion { 19 | let msg: String 20 | if let actual = message.actualValue { 21 | msg = "got: \(actual) \(message.postfixActual)" 22 | } else { 23 | msg = "expected \(message.to) \(message.postfixMessage)" 24 | } 25 | recordFailure("\(msg)\n", location: location) 26 | } 27 | } 28 | } 29 | 30 | /// Fallback handler in case XCTest is unavailable. This assertion handler will abort 31 | /// the program if it is invoked. 32 | class NimbleXCTestUnavailableHandler: AssertionHandler { 33 | func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) { 34 | fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.") 35 | } 36 | } 37 | 38 | #if !SWIFT_PACKAGE 39 | /// Helper class providing access to the currently executing XCTestCase instance, if any 40 | @objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation { 41 | @objc static let sharedInstance = CurrentTestCaseTracker() 42 | 43 | private(set) var currentTestCase: XCTestCase? 44 | 45 | private var stashed_swift_reportFatalErrorsToDebugger: Bool = false 46 | 47 | @objc func testCaseWillStart(_ testCase: XCTestCase) { 48 | #if swift(>=3.2) 49 | stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger 50 | _swift_reportFatalErrorsToDebugger = false 51 | #endif 52 | 53 | currentTestCase = testCase 54 | } 55 | 56 | @objc func testCaseDidFinish(_ testCase: XCTestCase) { 57 | currentTestCase = nil 58 | 59 | #if swift(>=3.2) 60 | _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger 61 | #endif 62 | } 63 | } 64 | #endif 65 | 66 | func isXCTestAvailable() -> Bool { 67 | #if canImport(Darwin) 68 | // XCTest is weakly linked and so may not be present 69 | return NSClassFromString("XCTestCase") != nil 70 | #else 71 | return true 72 | #endif 73 | } 74 | 75 | public func recordFailure(_ message: String, location: SourceLocation) { 76 | #if SWIFT_PACKAGE 77 | XCTFail("\(message)", file: location.file, line: location.line) 78 | #else 79 | if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase { 80 | let line = Int(location.line) 81 | testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true) 82 | } else { 83 | let msg = """ 84 | Attempted to report a test failure to XCTest while no test case was running. The failure was: 85 | \"\(message)\" 86 | It occurred at: \(location.file):\(location.line) 87 | """ 88 | NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() 89 | } 90 | #endif 91 | } 92 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/DSL.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Make an expectation on a given actual value. The value given is lazily evaluated. 4 | public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation { 5 | return Expectation( 6 | expression: Expression( 7 | expression: expression, 8 | location: SourceLocation(file: file, line: line), 9 | isClosure: true)) 10 | } 11 | 12 | /// Make an expectation on a given actual value. The closure is lazily invoked. 13 | public func expect(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation { 14 | return Expectation( 15 | expression: Expression( 16 | expression: expression, 17 | location: SourceLocation(file: file, line: line), 18 | isClosure: true)) 19 | } 20 | 21 | /// Always fails the test with a message and a specified location. 22 | public func fail(_ message: String, location: SourceLocation) { 23 | let handler = NimbleEnvironment.activeInstance.assertionHandler 24 | handler.assert(false, message: FailureMessage(stringValue: message), location: location) 25 | } 26 | 27 | /// Always fails the test with a message. 28 | public func fail(_ message: String, file: FileString = #file, line: UInt = #line) { 29 | fail(message, location: SourceLocation(file: file, line: line)) 30 | } 31 | 32 | /// Always fails the test. 33 | public func fail(_ file: FileString = #file, line: UInt = #line) { 34 | fail("fail() always fails", file: file, line: line) 35 | } 36 | 37 | /// Like Swift's precondition(), but raises NSExceptions instead of sigaborts 38 | internal func nimblePrecondition( 39 | _ expr: @autoclosure() -> Bool, 40 | _ name: @autoclosure() -> String, 41 | _ message: @autoclosure() -> String, 42 | file: StaticString = #file, 43 | line: UInt = #line) { 44 | let result = expr() 45 | if !result { 46 | #if canImport(Darwin) 47 | let exception = NSException( 48 | name: NSExceptionName(name()), 49 | reason: message(), 50 | userInfo: nil 51 | ) 52 | exception.raise() 53 | #else 54 | preconditionFailure("\(name()) - \(message())", file: file, line: line) 55 | #endif 56 | } 57 | } 58 | 59 | internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never { 60 | // swiftlint:disable line_length 61 | fatalError( 62 | """ 63 | Nimble Bug Found: \(msg) at \(file):\(line). 64 | Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the code snippet that caused this error. 65 | """ 66 | ) 67 | // swiftlint:enable line_length 68 | } 69 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Expectation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Deprecated 4 | internal func expressionDoesNotMatch(_ expression: Expression, matcher: U, toNot: String, description: String?) -> (Bool, FailureMessage) 5 | where U: Matcher, U.ValueType == T { 6 | let msg = FailureMessage() 7 | msg.userDescription = description 8 | msg.to = toNot 9 | do { 10 | let pass = try matcher.doesNotMatch(expression, failureMessage: msg) 11 | if msg.actualValue == "" { 12 | msg.actualValue = "<\(stringify(try expression.evaluate()))>" 13 | } 14 | return (pass, msg) 15 | } catch let error { 16 | msg.stringValue = "unexpected error thrown: <\(error)>" 17 | return (false, msg) 18 | } 19 | } 20 | 21 | internal func execute(_ expression: Expression, _ style: ExpectationStyle, _ predicate: Predicate, to: String, description: String?, captureExceptions: Bool = true) -> (Bool, FailureMessage) { 22 | func run() -> (Bool, FailureMessage) { 23 | let msg = FailureMessage() 24 | msg.userDescription = description 25 | msg.to = to 26 | do { 27 | let result = try predicate.satisfies(expression) 28 | result.message.update(failureMessage: msg) 29 | if msg.actualValue == "" { 30 | msg.actualValue = "<\(stringify(try expression.evaluate()))>" 31 | } 32 | return (result.toBoolean(expectation: style), msg) 33 | } catch let error { 34 | msg.stringValue = "unexpected error thrown: <\(error)>" 35 | return (false, msg) 36 | } 37 | } 38 | 39 | var result: (Bool, FailureMessage) = (false, FailureMessage()) 40 | if captureExceptions { 41 | let capture = NMBExceptionCapture(handler: ({ exception -> Void in 42 | let msg = FailureMessage() 43 | msg.stringValue = "unexpected exception raised: \(exception)" 44 | result = (false, msg) 45 | }), finally: nil) 46 | capture.tryBlock { 47 | result = run() 48 | } 49 | } else { 50 | result = run() 51 | } 52 | 53 | return result 54 | } 55 | 56 | public struct Expectation { 57 | 58 | public let expression: Expression 59 | 60 | public init(expression: Expression) { 61 | self.expression = expression 62 | } 63 | 64 | public func verify(_ pass: Bool, _ message: FailureMessage) { 65 | let handler = NimbleEnvironment.activeInstance.assertionHandler 66 | handler.assert(pass, message: message, location: expression.location) 67 | } 68 | 69 | ////////////////// OLD API ///////////////////// 70 | 71 | /// DEPRECATED: Tests the actual value using a matcher to match. 72 | public func to(_ matcher: U, description: String? = nil) 73 | where U: Matcher, U.ValueType == T { 74 | let (pass, msg) = execute( 75 | expression, 76 | .toMatch, 77 | matcher.predicate, 78 | to: "to", 79 | description: description, 80 | captureExceptions: false 81 | ) 82 | verify(pass, msg) 83 | } 84 | 85 | /// DEPRECATED: Tests the actual value using a matcher to not match. 86 | public func toNot(_ matcher: U, description: String? = nil) 87 | where U: Matcher, U.ValueType == T { 88 | // swiftlint:disable:next line_length 89 | let (pass, msg) = expressionDoesNotMatch(expression, matcher: matcher, toNot: "to not", description: description) 90 | verify(pass, msg) 91 | } 92 | 93 | /// DEPRECATED: Tests the actual value using a matcher to not match. 94 | /// 95 | /// Alias to toNot(). 96 | public func notTo(_ matcher: U, description: String? = nil) 97 | where U: Matcher, U.ValueType == T { 98 | toNot(matcher, description: description) 99 | } 100 | 101 | ////////////////// NEW API ///////////////////// 102 | 103 | /// Tests the actual value using a matcher to match. 104 | public func to(_ predicate: Predicate, description: String? = nil) { 105 | let (pass, msg) = execute(expression, .toMatch, predicate, to: "to", description: description) 106 | verify(pass, msg) 107 | } 108 | 109 | /// Tests the actual value using a matcher to not match. 110 | public func toNot(_ predicate: Predicate, description: String? = nil) { 111 | let (pass, msg) = execute(expression, .toNotMatch, predicate, to: "to not", description: description) 112 | verify(pass, msg) 113 | } 114 | 115 | /// Tests the actual value using a matcher to not match. 116 | /// 117 | /// Alias to toNot(). 118 | public func notTo(_ predicate: Predicate, description: String? = nil) { 119 | toNot(predicate, description: description) 120 | } 121 | 122 | // see: 123 | // - `async` for extension 124 | // - NMBExpectation for Objective-C interface 125 | } 126 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Expression.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Memoizes the given closure, only calling the passed 4 | // closure once; even if repeat calls to the returned closure 5 | internal func memoizedClosure(_ closure: @escaping () throws -> T) -> (Bool) throws -> T { 6 | var cache: T? 7 | return ({ withoutCaching in 8 | if withoutCaching || cache == nil { 9 | cache = try closure() 10 | } 11 | return cache! 12 | }) 13 | } 14 | 15 | /// Expression represents the closure of the value inside expect(...). 16 | /// Expressions are memoized by default. This makes them safe to call 17 | /// evaluate() multiple times without causing a re-evaluation of the underlying 18 | /// closure. 19 | /// 20 | /// @warning Since the closure can be any code, Objective-C code may choose 21 | /// to raise an exception. Currently, Expression does not memoize 22 | /// exception raising. 23 | /// 24 | /// This provides a common consumable API for matchers to utilize to allow 25 | /// Nimble to change internals to how the captured closure is managed. 26 | public struct Expression { 27 | // swiftlint:disable identifier_name 28 | internal let _expression: (Bool) throws -> T? 29 | internal let _withoutCaching: Bool 30 | // swiftlint:enable identifier_name 31 | public let location: SourceLocation 32 | public let isClosure: Bool 33 | 34 | /// Creates a new expression struct. Normally, expect(...) will manage this 35 | /// creation process. The expression is memoized. 36 | /// 37 | /// @param expression The closure that produces a given value. 38 | /// @param location The source location that this closure originates from. 39 | /// @param isClosure A bool indicating if the captured expression is a 40 | /// closure or internally produced closure. Some matchers 41 | /// may require closures. For example, toEventually() 42 | /// requires an explicit closure. This gives Nimble 43 | /// flexibility if @autoclosure behavior changes between 44 | /// Swift versions. Nimble internals always sets this true. 45 | public init(expression: @escaping () throws -> T?, location: SourceLocation, isClosure: Bool = true) { 46 | self._expression = memoizedClosure(expression) 47 | self.location = location 48 | self._withoutCaching = false 49 | self.isClosure = isClosure 50 | } 51 | 52 | /// Creates a new expression struct. Normally, expect(...) will manage this 53 | /// creation process. 54 | /// 55 | /// @param expression The closure that produces a given value. 56 | /// @param location The source location that this closure originates from. 57 | /// @param withoutCaching Indicates if the struct should memoize the given 58 | /// closure's result. Subsequent evaluate() calls will 59 | /// not call the given closure if this is true. 60 | /// @param isClosure A bool indicating if the captured expression is a 61 | /// closure or internally produced closure. Some matchers 62 | /// may require closures. For example, toEventually() 63 | /// requires an explicit closure. This gives Nimble 64 | /// flexibility if @autoclosure behavior changes between 65 | /// Swift versions. Nimble internals always sets this true. 66 | public init(memoizedExpression: @escaping (Bool) throws -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = true) { 67 | self._expression = memoizedExpression 68 | self.location = location 69 | self._withoutCaching = withoutCaching 70 | self.isClosure = isClosure 71 | } 72 | 73 | /// Returns a new Expression from the given expression. Identical to a map() 74 | /// on this type. This should be used only to typecast the Expression's 75 | /// closure value. 76 | /// 77 | /// The returned expression will preserve location and isClosure. 78 | /// 79 | /// @param block The block that can cast the current Expression value to a 80 | /// new type. 81 | public func cast(_ block: @escaping (T?) throws -> U?) -> Expression { 82 | return Expression( 83 | expression: ({ try block(self.evaluate()) }), 84 | location: self.location, 85 | isClosure: self.isClosure 86 | ) 87 | } 88 | 89 | public func evaluate() throws -> T? { 90 | return try self._expression(_withoutCaching) 91 | } 92 | 93 | public func withoutCaching() -> Expression { 94 | return Expression( 95 | memoizedExpression: self._expression, 96 | location: location, 97 | withoutCaching: true, 98 | isClosure: isClosure 99 | ) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/FailureMessage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Encapsulates the failure message that matchers can report to the end user. 4 | /// 5 | /// This is shared state between Nimble and matchers that mutate this value. 6 | public class FailureMessage: NSObject { 7 | public var expected: String = "expected" 8 | public var actualValue: String? = "" // empty string -> use default; nil -> exclude 9 | public var to: String = "to" 10 | public var postfixMessage: String = "match" 11 | public var postfixActual: String = "" 12 | /// An optional message that will be appended as a new line and provides additional details 13 | /// about the failure. This message will only be visible in the issue navigator / in logs but 14 | /// not directly in the source editor since only a single line is presented there. 15 | public var extendedMessage: String? 16 | public var userDescription: String? 17 | 18 | public var stringValue: String { 19 | get { 20 | if let value = _stringValueOverride { 21 | return value 22 | } else { 23 | return computeStringValue() 24 | } 25 | } 26 | set { 27 | _stringValueOverride = newValue 28 | } 29 | } 30 | 31 | // swiftlint:disable:next identifier_name 32 | internal var _stringValueOverride: String? 33 | internal var hasOverriddenStringValue: Bool { 34 | return _stringValueOverride != nil 35 | } 36 | 37 | public override init() { 38 | } 39 | 40 | public init(stringValue: String) { 41 | _stringValueOverride = stringValue 42 | } 43 | 44 | internal func stripNewlines(_ str: String) -> String { 45 | let whitespaces = CharacterSet.whitespacesAndNewlines 46 | return str 47 | .components(separatedBy: "\n") 48 | .map { line in line.trimmingCharacters(in: whitespaces) } 49 | .joined(separator: "") 50 | } 51 | 52 | internal func computeStringValue() -> String { 53 | var value = "\(expected) \(to) \(postfixMessage)" 54 | if let actualValue = actualValue { 55 | value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)" 56 | } 57 | value = stripNewlines(value) 58 | 59 | if let extendedMessage = extendedMessage { 60 | value += "\n\(stripNewlines(extendedMessage))" 61 | } 62 | 63 | if let userDescription = userDescription { 64 | return "\(userDescription)\n\(value)" 65 | } 66 | 67 | return value 68 | } 69 | 70 | internal func appendMessage(_ msg: String) { 71 | if hasOverriddenStringValue { 72 | stringValue += "\(msg)" 73 | } else if actualValue != nil { 74 | postfixActual += msg 75 | } else { 76 | postfixMessage += msg 77 | } 78 | } 79 | 80 | internal func appendDetails(_ msg: String) { 81 | if hasOverriddenStringValue { 82 | if let desc = userDescription { 83 | stringValue = "\(desc)\n\(stringValue)" 84 | } 85 | stringValue += "\n\(msg)" 86 | } else { 87 | if let desc = userDescription { 88 | userDescription = desc 89 | } 90 | extendedMessage = msg 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private func matcherMessage(forType expectedType: T.Type) -> String { 4 | return "be a kind of \(String(describing: expectedType))" 5 | } 6 | private func matcherMessage(forClass expectedClass: AnyClass) -> String { 7 | return "be a kind of \(String(describing: expectedClass))" 8 | } 9 | 10 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class. 11 | public func beAKindOf(_ expectedType: T.Type) -> Predicate { 12 | return Predicate.define { actualExpression in 13 | let message: ExpectationMessage 14 | 15 | let instance = try actualExpression.evaluate() 16 | guard let validInstance = instance else { 17 | message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "") 18 | return PredicateResult(status: .fail, message: message) 19 | } 20 | message = .expectedCustomValueTo( 21 | "be a kind of \(String(describing: expectedType))", 22 | "<\(String(describing: type(of: validInstance))) instance>" 23 | ) 24 | 25 | return PredicateResult( 26 | bool: validInstance is T, 27 | message: message 28 | ) 29 | } 30 | } 31 | 32 | #if canImport(Darwin) 33 | 34 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class. 35 | /// @see beAnInstanceOf if you want to match against the exact class 36 | public func beAKindOf(_ expectedClass: AnyClass) -> Predicate { 37 | return Predicate.define { actualExpression in 38 | let message: ExpectationMessage 39 | let status: PredicateStatus 40 | 41 | let instance = try actualExpression.evaluate() 42 | if let validInstance = instance { 43 | status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass)) 44 | message = .expectedCustomValueTo( 45 | matcherMessage(forClass: expectedClass), 46 | "<\(String(describing: type(of: validInstance))) instance>" 47 | ) 48 | } else { 49 | status = .fail 50 | message = .expectedCustomValueTo( 51 | matcherMessage(forClass: expectedClass), 52 | "" 53 | ) 54 | } 55 | 56 | return PredicateResult(status: status, message: message) 57 | } 58 | } 59 | 60 | extension NMBObjCMatcher { 61 | @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher { 62 | return NMBPredicate { actualExpression in 63 | return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC() 64 | } 65 | } 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class. 4 | public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate { 5 | let errorMessage = "be an instance of \(String(describing: expectedType))" 6 | return Predicate.define { actualExpression in 7 | let instance = try actualExpression.evaluate() 8 | guard let validInstance = instance else { 9 | return PredicateResult( 10 | status: .doesNotMatch, 11 | message: .expectedActualValueTo(errorMessage) 12 | ) 13 | } 14 | 15 | let actualString = "<\(String(describing: type(of: validInstance))) instance>" 16 | 17 | return PredicateResult( 18 | status: PredicateStatus(bool: type(of: validInstance) == expectedType), 19 | message: .expectedCustomValueTo(errorMessage, actualString) 20 | ) 21 | } 22 | } 23 | 24 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class. 25 | /// @see beAKindOf if you want to match against subclasses 26 | public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate { 27 | let errorMessage = "be an instance of \(String(describing: expectedClass))" 28 | return Predicate.define { actualExpression in 29 | let instance = try actualExpression.evaluate() 30 | let actualString: String 31 | if let validInstance = instance { 32 | actualString = "<\(String(describing: type(of: validInstance))) instance>" 33 | } else { 34 | actualString = "" 35 | } 36 | #if canImport(Darwin) 37 | let matches = instance != nil && instance!.isMember(of: expectedClass) 38 | #else 39 | let matches = instance != nil && type(of: instance!) == expectedClass 40 | #endif 41 | return PredicateResult( 42 | status: PredicateStatus(bool: matches), 43 | message: .expectedCustomValueTo(errorMessage, actualString) 44 | ) 45 | } 46 | } 47 | 48 | #if canImport(Darwin) 49 | extension NMBObjCMatcher { 50 | @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher { 51 | return NMBPredicate { actualExpression in 52 | return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC() 53 | } 54 | } 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeEmpty.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 4 | /// means the are no items in that collection. For strings, it is an empty string. 5 | public func beEmpty() -> Predicate { 6 | return Predicate.simple("be empty") { actualExpression in 7 | guard let actual = try actualExpression.evaluate() else { 8 | return .fail 9 | } 10 | var generator = actual.makeIterator() 11 | return PredicateStatus(bool: generator.next() == nil) 12 | } 13 | } 14 | 15 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 16 | /// means the are no items in that collection. For strings, it is an empty string. 17 | public func beEmpty() -> Predicate { 18 | return Predicate.simple("be empty") { actualExpression in 19 | guard let actual = try actualExpression.evaluate() else { 20 | return .fail 21 | } 22 | return PredicateStatus(bool: actual.isEmpty) 23 | } 24 | } 25 | 26 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 27 | /// means the are no items in that collection. For strings, it is an empty string. 28 | public func beEmpty() -> Predicate { 29 | return Predicate.simple("be empty") { actualExpression in 30 | guard let actual = try actualExpression.evaluate() else { 31 | return .fail 32 | } 33 | return PredicateStatus(bool: actual.isEmpty) 34 | } 35 | } 36 | 37 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 38 | /// means the are no items in that collection. For strings, it is an empty string. 39 | public func beEmpty() -> Predicate { 40 | return Predicate.simple("be empty") { actualExpression in 41 | let actualString = try actualExpression.evaluate() 42 | return PredicateStatus(bool: actualString == nil || NSString(string: actualString!).length == 0) 43 | } 44 | } 45 | 46 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 47 | /// means the are no items in that collection. For NSString instances, it is an empty string. 48 | public func beEmpty() -> Predicate { 49 | return Predicate.simple("be empty") { actualExpression in 50 | let actualString = try actualExpression.evaluate() 51 | return PredicateStatus(bool: actualString == nil || actualString!.length == 0) 52 | } 53 | } 54 | 55 | // Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray, 56 | // etc, since they conform to Sequence as well as NMBCollection. 57 | 58 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 59 | /// means the are no items in that collection. For strings, it is an empty string. 60 | public func beEmpty() -> Predicate { 61 | return Predicate.simple("be empty") { actualExpression in 62 | let actualDictionary = try actualExpression.evaluate() 63 | return PredicateStatus(bool: actualDictionary == nil || actualDictionary!.count == 0) 64 | } 65 | } 66 | 67 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 68 | /// means the are no items in that collection. For strings, it is an empty string. 69 | public func beEmpty() -> Predicate { 70 | return Predicate.simple("be empty") { actualExpression in 71 | let actualArray = try actualExpression.evaluate() 72 | return PredicateStatus(bool: actualArray == nil || actualArray!.count == 0) 73 | } 74 | } 75 | 76 | /// A Nimble matcher that succeeds when a value is "empty". For collections, this 77 | /// means the are no items in that collection. For strings, it is an empty string. 78 | public func beEmpty() -> Predicate { 79 | return Predicate.simple("be empty") { actualExpression in 80 | let actual = try actualExpression.evaluate() 81 | return PredicateStatus(bool: actual == nil || actual!.count == 0) 82 | } 83 | } 84 | 85 | #if canImport(Darwin) 86 | extension NMBObjCMatcher { 87 | @objc public class func beEmptyMatcher() -> NMBPredicate { 88 | return NMBPredicate { actualExpression in 89 | let location = actualExpression.location 90 | let actualValue = try actualExpression.evaluate() 91 | 92 | if let value = actualValue as? NMBCollection { 93 | let expr = Expression(expression: ({ value as NMBCollection }), location: location) 94 | return try beEmpty().satisfies(expr).toObjectiveC() 95 | } else if let value = actualValue as? NSString { 96 | let expr = Expression(expression: ({ value as String }), location: location) 97 | return try beEmpty().satisfies(expr).toObjectiveC() 98 | } else if let actualValue = actualValue { 99 | // swiftlint:disable:next line_length 100 | let badTypeErrorMsg = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" 101 | return NMBPredicateResult( 102 | status: NMBPredicateStatus.fail, 103 | message: NMBExpectationMessage( 104 | expectedActualValueTo: badTypeErrorMsg, 105 | customActualValue: "\(String(describing: type(of: actualValue))) type" 106 | ) 107 | ) 108 | } 109 | return NMBPredicateResult( 110 | status: NMBPredicateStatus.fail, 111 | message: NMBExpectationMessage(expectedActualValueTo: "be empty").appendedBeNilHint() 112 | ) 113 | } 114 | } 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value. 4 | public func beGreaterThan(_ expectedValue: T?) -> Predicate { 5 | let errorMessage = "be greater than <\(stringify(expectedValue))>" 6 | return Predicate.simple(errorMessage) { actualExpression in 7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue { 8 | return PredicateStatus(bool: actual > expected) 9 | } 10 | return .fail 11 | } 12 | } 13 | 14 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value. 15 | public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate { 16 | let errorMessage = "be greater than <\(stringify(expectedValue))>" 17 | return Predicate.simple(errorMessage) { actualExpression in 18 | let actualValue = try actualExpression.evaluate() 19 | let matches = actualValue != nil 20 | && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending 21 | return PredicateStatus(bool: matches) 22 | } 23 | } 24 | 25 | public func >(lhs: Expectation, rhs: T) { 26 | lhs.to(beGreaterThan(rhs)) 27 | } 28 | 29 | public func > (lhs: Expectation, rhs: NMBComparable?) { 30 | lhs.to(beGreaterThan(rhs)) 31 | } 32 | 33 | #if canImport(Darwin) 34 | extension NMBObjCMatcher { 35 | @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBMatcher { 36 | return NMBPredicate { actualExpression in 37 | let expr = actualExpression.cast { $0 as? NMBComparable } 38 | return try beGreaterThan(expected).satisfies(expr).toObjectiveC() 39 | } 40 | } 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is greater than 4 | /// or equal to the expected value. 5 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { 6 | let message = "be greater than or equal to <\(stringify(expectedValue))>" 7 | return Predicate.simple(message) { actualExpression in 8 | let actualValue = try actualExpression.evaluate() 9 | if let actual = actualValue, let expected = expectedValue { 10 | return PredicateStatus(bool: actual >= expected) 11 | } 12 | return .fail 13 | } 14 | } 15 | 16 | /// A Nimble matcher that succeeds when the actual value is greater than 17 | /// or equal to the expected value. 18 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate { 19 | let message = "be greater than or equal to <\(stringify(expectedValue))>" 20 | return Predicate.simple(message) { actualExpression in 21 | let actualValue = try actualExpression.evaluate() 22 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending 23 | return PredicateStatus(bool: matches) 24 | } 25 | } 26 | 27 | public func >=(lhs: Expectation, rhs: T) { 28 | lhs.to(beGreaterThanOrEqualTo(rhs)) 29 | } 30 | 31 | public func >=(lhs: Expectation, rhs: T) { 32 | lhs.to(beGreaterThanOrEqualTo(rhs)) 33 | } 34 | 35 | #if canImport(Darwin) 36 | extension NMBObjCMatcher { 37 | @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher { 38 | return NMBPredicate { actualExpression in 39 | let expr = actualExpression.cast { $0 as? NMBComparable } 40 | return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC() 41 | } 42 | } 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is the same instance 4 | /// as the expected instance. 5 | public func beIdenticalTo(_ expected: Any?) -> Predicate { 6 | return Predicate.define { actualExpression in 7 | #if os(Linux) && !swift(>=4.1.50) 8 | let actual = try actualExpression.evaluate() as? AnyObject 9 | #else 10 | let actual = try actualExpression.evaluate() as AnyObject? 11 | #endif 12 | 13 | let bool: Bool 14 | #if os(Linux) && !swift(>=4.1.50) 15 | bool = actual === (expected as? AnyObject) && actual !== nil 16 | #else 17 | bool = actual === (expected as AnyObject?) && actual !== nil 18 | #endif 19 | return PredicateResult( 20 | bool: bool, 21 | message: .expectedCustomValueTo( 22 | "be identical to \(identityAsString(expected))", 23 | "\(identityAsString(actual))" 24 | ) 25 | ) 26 | } 27 | } 28 | 29 | public func === (lhs: Expectation, rhs: Any?) { 30 | lhs.to(beIdenticalTo(rhs)) 31 | } 32 | public func !== (lhs: Expectation, rhs: Any?) { 33 | lhs.toNot(beIdenticalTo(rhs)) 34 | } 35 | 36 | /// A Nimble matcher that succeeds when the actual value is the same instance 37 | /// as the expected instance. 38 | /// 39 | /// Alias for "beIdenticalTo". 40 | public func be(_ expected: Any?) -> Predicate { 41 | return beIdenticalTo(expected) 42 | } 43 | 44 | #if canImport(Darwin) 45 | extension NMBObjCMatcher { 46 | @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBMatcher { 47 | return NMBPredicate { actualExpression in 48 | let aExpr = actualExpression.cast { $0 as Any? } 49 | return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC() 50 | } 51 | } 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is less than the expected value. 4 | public func beLessThan(_ expectedValue: T?) -> Predicate { 5 | let message = "be less than <\(stringify(expectedValue))>" 6 | return Predicate.simple(message) { actualExpression in 7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue { 8 | return PredicateStatus(bool: actual < expected) 9 | } 10 | return .fail 11 | } 12 | } 13 | 14 | /// A Nimble matcher that succeeds when the actual value is less than the expected value. 15 | public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate { 16 | let message = "be less than <\(stringify(expectedValue))>" 17 | return Predicate.simple(message) { actualExpression in 18 | let actualValue = try actualExpression.evaluate() 19 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending 20 | return PredicateStatus(bool: matches) 21 | } 22 | } 23 | 24 | public func <(lhs: Expectation, rhs: T) { 25 | lhs.to(beLessThan(rhs)) 26 | } 27 | 28 | public func < (lhs: Expectation, rhs: NMBComparable?) { 29 | lhs.to(beLessThan(rhs)) 30 | } 31 | 32 | #if canImport(Darwin) 33 | extension NMBObjCMatcher { 34 | @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBMatcher { 35 | return NMBPredicate { actualExpression in 36 | let expr = actualExpression.cast { $0 as? NMBComparable } 37 | return try beLessThan(expected).satisfies(expr).toObjectiveC() 38 | } 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is less than 4 | /// or equal to the expected value. 5 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { 6 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in 7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue { 8 | return PredicateStatus(bool: actual <= expected) 9 | } 10 | return .fail 11 | } 12 | } 13 | 14 | /// A Nimble matcher that succeeds when the actual value is less than 15 | /// or equal to the expected value. 16 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate { 17 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in 18 | let actualValue = try actualExpression.evaluate() 19 | let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false 20 | return PredicateStatus(bool: matches) 21 | } 22 | } 23 | 24 | public func <=(lhs: Expectation, rhs: T) { 25 | lhs.to(beLessThanOrEqualTo(rhs)) 26 | } 27 | 28 | public func <=(lhs: Expectation, rhs: T) { 29 | lhs.to(beLessThanOrEqualTo(rhs)) 30 | } 31 | 32 | #if canImport(Darwin) 33 | extension NMBObjCMatcher { 34 | @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher { 35 | return NMBPredicate { actualExpression in 36 | let expr = actualExpression.cast { $0 as? NMBComparable } 37 | return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC() 38 | } 39 | } 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeLogical.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Int8: ExpressibleByBooleanLiteral { 4 | public init(booleanLiteral value: Bool) { 5 | self = NSNumber(value: value).int8Value 6 | } 7 | } 8 | 9 | extension UInt8: ExpressibleByBooleanLiteral { 10 | public init(booleanLiteral value: Bool) { 11 | self = NSNumber(value: value).uint8Value 12 | } 13 | } 14 | 15 | extension Int16: ExpressibleByBooleanLiteral { 16 | public init(booleanLiteral value: Bool) { 17 | self = NSNumber(value: value).int16Value 18 | } 19 | } 20 | 21 | extension UInt16: ExpressibleByBooleanLiteral { 22 | public init(booleanLiteral value: Bool) { 23 | self = NSNumber(value: value).uint16Value 24 | } 25 | } 26 | 27 | extension Int32: ExpressibleByBooleanLiteral { 28 | public init(booleanLiteral value: Bool) { 29 | self = NSNumber(value: value).int32Value 30 | } 31 | } 32 | 33 | extension UInt32: ExpressibleByBooleanLiteral { 34 | public init(booleanLiteral value: Bool) { 35 | self = NSNumber(value: value).uint32Value 36 | } 37 | } 38 | 39 | extension Int64: ExpressibleByBooleanLiteral { 40 | public init(booleanLiteral value: Bool) { 41 | self = NSNumber(value: value).int64Value 42 | } 43 | } 44 | 45 | extension UInt64: ExpressibleByBooleanLiteral { 46 | public init(booleanLiteral value: Bool) { 47 | self = NSNumber(value: value).uint64Value 48 | } 49 | } 50 | 51 | extension Float: ExpressibleByBooleanLiteral { 52 | public init(booleanLiteral value: Bool) { 53 | self = NSNumber(value: value).floatValue 54 | } 55 | } 56 | 57 | extension Double: ExpressibleByBooleanLiteral { 58 | public init(booleanLiteral value: Bool) { 59 | self = NSNumber(value: value).doubleValue 60 | } 61 | } 62 | 63 | extension Int: ExpressibleByBooleanLiteral { 64 | public init(booleanLiteral value: Bool) { 65 | self = NSNumber(value: value).intValue 66 | } 67 | } 68 | 69 | extension UInt: ExpressibleByBooleanLiteral { 70 | public init(booleanLiteral value: Bool) { 71 | self = NSNumber(value: value).uintValue 72 | } 73 | } 74 | 75 | internal func rename(_ matcher: Predicate, failureMessage message: ExpectationMessage) -> Predicate { 76 | return Predicate { actualExpression in 77 | let result = try matcher.satisfies(actualExpression) 78 | return PredicateResult(status: result.status, message: message) 79 | }.requireNonNil 80 | } 81 | 82 | // MARK: beTrue() / beFalse() 83 | 84 | /// A Nimble matcher that succeeds when the actual value is exactly true. 85 | /// This matcher will not match against nils. 86 | public func beTrue() -> Predicate { 87 | return rename(equal(true), failureMessage: .expectedActualValueTo("be true")) 88 | } 89 | 90 | /// A Nimble matcher that succeeds when the actual value is exactly false. 91 | /// This matcher will not match against nils. 92 | public func beFalse() -> Predicate { 93 | return rename(equal(false), failureMessage: .expectedActualValueTo("be false")) 94 | } 95 | 96 | // MARK: beTruthy() / beFalsy() 97 | 98 | /// A Nimble matcher that succeeds when the actual value is not logically false. 99 | public func beTruthy() -> Predicate { 100 | return Predicate.simpleNilable("be truthy") { actualExpression in 101 | let actualValue = try actualExpression.evaluate() 102 | if let actualValue = actualValue { 103 | return PredicateStatus(bool: actualValue == (true as T)) 104 | } 105 | return PredicateStatus(bool: actualValue != nil) 106 | } 107 | } 108 | 109 | /// A Nimble matcher that succeeds when the actual value is logically false. 110 | /// This matcher will match against nils. 111 | public func beFalsy() -> Predicate { 112 | return Predicate.simpleNilable("be falsy") { actualExpression in 113 | let actualValue = try actualExpression.evaluate() 114 | if let actualValue = actualValue { 115 | return PredicateStatus(bool: actualValue == (false as T)) 116 | } 117 | return PredicateStatus(bool: actualValue == nil) 118 | } 119 | } 120 | 121 | #if canImport(Darwin) 122 | extension NMBObjCMatcher { 123 | @objc public class func beTruthyMatcher() -> NMBMatcher { 124 | return NMBPredicate { actualExpression in 125 | let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } 126 | return try beTruthy().satisfies(expr).toObjectiveC() 127 | } 128 | } 129 | 130 | @objc public class func beFalsyMatcher() -> NMBMatcher { 131 | return NMBPredicate { actualExpression in 132 | let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } 133 | return try beFalsy().satisfies(expr).toObjectiveC() 134 | } 135 | } 136 | 137 | @objc public class func beTrueMatcher() -> NMBMatcher { 138 | return NMBPredicate { actualExpression in 139 | let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false } 140 | return try beTrue().satisfies(expr).toObjectiveC() 141 | } 142 | } 143 | 144 | @objc public class func beFalseMatcher() -> NMBMatcher { 145 | return NMBPredicate { actualExpression in 146 | let expr = actualExpression.cast { value -> Bool? in 147 | guard let value = value else { return nil } 148 | return (value as? NSNumber)?.boolValue ?? false 149 | } 150 | return try beFalse().satisfies(expr).toObjectiveC() 151 | } 152 | } 153 | } 154 | #endif 155 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is nil. 4 | public func beNil() -> Predicate { 5 | return Predicate.simpleNilable("be nil") { actualExpression in 6 | let actualValue = try actualExpression.evaluate() 7 | return PredicateStatus(bool: actualValue == nil) 8 | } 9 | } 10 | 11 | #if canImport(Darwin) 12 | extension NMBObjCMatcher { 13 | @objc public class func beNilMatcher() -> NMBMatcher { 14 | return NMBPredicate { actualExpression in 15 | return try beNil().satisfies(actualExpression).toObjectiveC() 16 | } 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is Void. 4 | public func beVoid() -> Predicate<()> { 5 | return Predicate.simpleNilable("be void") { actualExpression in 6 | let actualValue: ()? = try actualExpression.evaluate() 7 | return PredicateStatus(bool: actualValue != nil) 8 | } 9 | } 10 | 11 | extension Expectation where T == () { 12 | public static func == (lhs: Expectation<()>, rhs: ()) { 13 | lhs.to(beVoid()) 14 | } 15 | 16 | public static func != (lhs: Expectation<()>, rhs: ()) { 17 | lhs.toNot(beVoid()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/BeginWith.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual sequence's first element 4 | /// is equal to the expected value. 5 | public func beginWith(_ startingElement: T) -> Predicate 6 | where S.Iterator.Element == T { 7 | return Predicate.simple("begin with <\(startingElement)>") { actualExpression in 8 | if let actualValue = try actualExpression.evaluate() { 9 | var actualGenerator = actualValue.makeIterator() 10 | return PredicateStatus(bool: actualGenerator.next() == startingElement) 11 | } 12 | return .fail 13 | } 14 | } 15 | 16 | /// A Nimble matcher that succeeds when the actual collection's first element 17 | /// is equal to the expected object. 18 | public func beginWith(_ startingElement: Any) -> Predicate { 19 | return Predicate.simple("begin with <\(startingElement)>") { actualExpression in 20 | guard let collection = try actualExpression.evaluate() else { return .fail } 21 | guard collection.count > 0 else { return .doesNotMatch } 22 | #if os(Linux) 23 | guard let collectionValue = collection.object(at: 0) as? NSObject else { 24 | return .fail 25 | } 26 | #else 27 | let collectionValue = collection.object(at: 0) as AnyObject 28 | #endif 29 | return PredicateStatus(bool: collectionValue.isEqual(startingElement)) 30 | } 31 | } 32 | 33 | /// A Nimble matcher that succeeds when the actual string contains expected substring 34 | /// where the expected substring's location is zero. 35 | public func beginWith(_ startingSubstring: String) -> Predicate { 36 | return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in 37 | if let actual = try actualExpression.evaluate() { 38 | return PredicateStatus(bool: actual.hasPrefix(startingSubstring)) 39 | } 40 | return .fail 41 | } 42 | } 43 | 44 | #if canImport(Darwin) 45 | extension NMBObjCMatcher { 46 | @objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher { 47 | return NMBPredicate { actualExpression in 48 | let actual = try actualExpression.evaluate() 49 | if actual is String { 50 | let expr = actualExpression.cast { $0 as? String } 51 | // swiftlint:disable:next force_cast 52 | return try beginWith(expected as! String).satisfies(expr).toObjectiveC() 53 | } else { 54 | let expr = actualExpression.cast { $0 as? NMBOrderedCollection } 55 | return try beginWith(expected).satisfies(expr).toObjectiveC() 56 | } 57 | } 58 | } 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T { 4 | 5 | return Predicate.define { actualExpression in 6 | let message: ExpectationMessage 7 | if predicateDescription == "" { 8 | message = .expectedTo("find object in collection that satisfies predicate") 9 | } else { 10 | message = .expectedTo("find object in collection \(predicateDescription)") 11 | } 12 | 13 | if let sequence = try actualExpression.evaluate() { 14 | for object in sequence { 15 | if predicate(object) { 16 | return PredicateResult(bool: true, message: message) 17 | } 18 | } 19 | 20 | return PredicateResult(bool: false, message: message) 21 | } 22 | 23 | return PredicateResult(status: .fail, message: message) 24 | } 25 | } 26 | 27 | #if canImport(Darwin) 28 | extension NMBObjCMatcher { 29 | @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBMatcher { 30 | return NMBPredicate { actualExpression in 31 | let value = try actualExpression.evaluate() 32 | guard let enumeration = value as? NSFastEnumeration else { 33 | let message = ExpectationMessage.fail( 34 | "containElementSatisfying must be provided an NSFastEnumeration object" 35 | ) 36 | return NMBPredicateResult(status: .fail, message: message.toObjectiveC()) 37 | } 38 | 39 | let message = ExpectationMessage 40 | .expectedTo("find object in collection that satisfies predicate") 41 | .toObjectiveC() 42 | 43 | var iterator = NSFastEnumerationIterator(enumeration) 44 | while let item = iterator.next() { 45 | guard let object = item as? NSObject else { 46 | continue 47 | } 48 | 49 | if predicate(object) { 50 | return NMBPredicateResult(status: .matches, message: message) 51 | } 52 | } 53 | 54 | return NMBPredicateResult(status: .doesNotMatch, message: message) 55 | } 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/ElementsEqual.swift: -------------------------------------------------------------------------------- 1 | /// A Nimble matcher that succeeds when the actual sequence contain the same elements in the same order to the exepected sequence. 2 | public func elementsEqual(_ expectedValue: S?) -> Predicate where S.Element: Equatable { 3 | // A matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal 4 | return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in 5 | let actualValue = try actualExpression.evaluate() 6 | switch (expectedValue, actualValue) { 7 | case (nil, _?): 8 | return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) 9 | case (nil, nil), (_, nil): 10 | return PredicateResult(status: .fail, message: msg) 11 | case (let expected?, let actual?): 12 | let matches = expected.elementsEqual(actual) 13 | return PredicateResult(bool: matches, message: msg) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/EndWith.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual sequence's last element 4 | /// is equal to the expected value. 5 | public func endWith(_ endingElement: T) -> Predicate 6 | where S.Iterator.Element == T { 7 | return Predicate.simple("end with <\(endingElement)>") { actualExpression in 8 | if let actualValue = try actualExpression.evaluate() { 9 | var actualGenerator = actualValue.makeIterator() 10 | var lastItem: T? 11 | var item: T? 12 | repeat { 13 | lastItem = item 14 | item = actualGenerator.next() 15 | } while(item != nil) 16 | 17 | return PredicateStatus(bool: lastItem == endingElement) 18 | } 19 | return .fail 20 | } 21 | } 22 | 23 | /// A Nimble matcher that succeeds when the actual collection's last element 24 | /// is equal to the expected object. 25 | public func endWith(_ endingElement: Any) -> Predicate { 26 | return Predicate.simple("end with <\(endingElement)>") { actualExpression in 27 | guard let collection = try actualExpression.evaluate() else { return .fail } 28 | guard collection.count > 0 else { return PredicateStatus(bool: false) } 29 | #if os(Linux) 30 | guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else { 31 | return .fail 32 | } 33 | #else 34 | let collectionValue = collection.object(at: collection.count - 1) as AnyObject 35 | #endif 36 | 37 | return PredicateStatus(bool: collectionValue.isEqual(endingElement)) 38 | } 39 | } 40 | 41 | /// A Nimble matcher that succeeds when the actual string contains the expected substring 42 | /// where the expected substring's location is the actual string's length minus the 43 | /// expected substring's length. 44 | public func endWith(_ endingSubstring: String) -> Predicate { 45 | return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in 46 | if let collection = try actualExpression.evaluate() { 47 | return PredicateStatus(bool: collection.hasSuffix(endingSubstring)) 48 | } 49 | return .fail 50 | } 51 | } 52 | 53 | #if canImport(Darwin) 54 | extension NMBObjCMatcher { 55 | @objc public class func endWithMatcher(_ expected: Any) -> NMBMatcher { 56 | return NMBPredicate { actualExpression in 57 | let actual = try actualExpression.evaluate() 58 | if actual is String { 59 | let expr = actualExpression.cast { $0 as? String } 60 | // swiftlint:disable:next force_cast 61 | return try endWith(expected as! String).satisfies(expr).toObjectiveC() 62 | } else { 63 | let expr = actualExpression.cast { $0 as? NMBOrderedCollection } 64 | return try endWith(expected).satisfies(expr).toObjectiveC() 65 | } 66 | } 67 | } 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/Equal.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value is equal to the expected value. 4 | /// Values can support equal by supporting the Equatable protocol. 5 | /// 6 | /// @see beCloseTo if you want to match imprecise types (eg - floats, doubles). 7 | public func equal(_ expectedValue: T?) -> Predicate { 8 | return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in 9 | let actualValue = try actualExpression.evaluate() 10 | switch (expectedValue, actualValue) { 11 | case (nil, _?): 12 | return PredicateResult(status: .fail, message: msg.appendedBeNilHint()) 13 | case (nil, nil), (_, nil): 14 | return PredicateResult(status: .fail, message: msg) 15 | case (let expected?, let actual?): 16 | let matches = expected == actual 17 | return PredicateResult(bool: matches, message: msg) 18 | } 19 | } 20 | } 21 | 22 | /// A Nimble matcher allowing comparison of collection with optional type 23 | public func equal(_ expectedValue: [T?]) -> Predicate<[T?]> { 24 | return Predicate.define("equal <\(stringify(expectedValue))>") { actualExpression, msg in 25 | guard let actualValue = try actualExpression.evaluate() else { 26 | return PredicateResult( 27 | status: .fail, 28 | message: msg.appendedBeNilHint() 29 | ) 30 | } 31 | 32 | let matches = expectedValue == actualValue 33 | return PredicateResult(bool: matches, message: msg) 34 | } 35 | } 36 | 37 | /// A Nimble matcher that succeeds when the actual set is equal to the expected set. 38 | public func equal(_ expectedValue: Set?) -> Predicate> { 39 | return equal(expectedValue, stringify: { stringify($0) }) 40 | } 41 | 42 | /// A Nimble matcher that succeeds when the actual set is equal to the expected set. 43 | public func equal(_ expectedValue: Set?) -> Predicate> { 44 | return equal(expectedValue, stringify: { 45 | if let set = $0 { 46 | return stringify(Array(set).sorted { $0 < $1 }) 47 | } else { 48 | return "nil" 49 | } 50 | }) 51 | } 52 | 53 | private func equal(_ expectedValue: Set?, stringify: @escaping (Set?) -> String) -> Predicate> { 54 | return Predicate { actualExpression in 55 | var errorMessage: ExpectationMessage = 56 | .expectedActualValueTo("equal <\(stringify(expectedValue))>") 57 | 58 | guard let expectedValue = expectedValue else { 59 | return PredicateResult( 60 | status: .fail, 61 | message: errorMessage.appendedBeNilHint() 62 | ) 63 | } 64 | 65 | guard let actualValue = try actualExpression.evaluate() else { 66 | return PredicateResult( 67 | status: .fail, 68 | message: errorMessage.appendedBeNilHint() 69 | ) 70 | } 71 | 72 | errorMessage = .expectedCustomValueTo( 73 | "equal <\(stringify(expectedValue))>", 74 | "<\(stringify(actualValue))>" 75 | ) 76 | 77 | if expectedValue == actualValue { 78 | return PredicateResult( 79 | status: .matches, 80 | message: errorMessage 81 | ) 82 | } 83 | 84 | let missing = expectedValue.subtracting(actualValue) 85 | if missing.count > 0 { 86 | errorMessage = errorMessage.appended(message: ", missing <\(stringify(missing))>") 87 | } 88 | 89 | let extra = actualValue.subtracting(expectedValue) 90 | if extra.count > 0 { 91 | errorMessage = errorMessage.appended(message: ", extra <\(stringify(extra))>") 92 | } 93 | return PredicateResult( 94 | status: .doesNotMatch, 95 | message: errorMessage 96 | ) 97 | } 98 | } 99 | 100 | public func ==(lhs: Expectation, rhs: T?) { 101 | lhs.to(equal(rhs)) 102 | } 103 | 104 | public func !=(lhs: Expectation, rhs: T?) { 105 | lhs.toNot(equal(rhs)) 106 | } 107 | 108 | public func ==(lhs: Expectation<[T]>, rhs: [T]?) { 109 | lhs.to(equal(rhs)) 110 | } 111 | 112 | public func !=(lhs: Expectation<[T]>, rhs: [T]?) { 113 | lhs.toNot(equal(rhs)) 114 | } 115 | 116 | public func == (lhs: Expectation>, rhs: Set?) { 117 | lhs.to(equal(rhs)) 118 | } 119 | 120 | public func != (lhs: Expectation>, rhs: Set?) { 121 | lhs.toNot(equal(rhs)) 122 | } 123 | 124 | public func ==(lhs: Expectation>, rhs: Set?) { 125 | lhs.to(equal(rhs)) 126 | } 127 | 128 | public func !=(lhs: Expectation>, rhs: Set?) { 129 | lhs.toNot(equal(rhs)) 130 | } 131 | 132 | public func ==(lhs: Expectation<[T: C]>, rhs: [T: C]?) { 133 | lhs.to(equal(rhs)) 134 | } 135 | 136 | public func !=(lhs: Expectation<[T: C]>, rhs: [T: C]?) { 137 | lhs.toNot(equal(rhs)) 138 | } 139 | 140 | #if canImport(Darwin) 141 | extension NMBObjCMatcher { 142 | @objc public class func equalMatcher(_ expected: NSObject) -> NMBMatcher { 143 | return NMBPredicate { actualExpression in 144 | return try equal(expected).satisfies(actualExpression).toObjectiveC() 145 | } 146 | } 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/HaveCount.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // The `haveCount` matchers do not print the full string representation of the collection value, 4 | // instead they only print the type name and the expected count. This makes it easier to understand 5 | // the reason for failed expectations. See: https://github.com/Quick/Nimble/issues/308. 6 | // The representation of the collection content is provided in a new line as an `extendedMessage`. 7 | 8 | /// A Nimble matcher that succeeds when the actual Collection's count equals 9 | /// the expected value 10 | public func haveCount(_ expectedValue: Int) -> Predicate { 11 | return Predicate.define { actualExpression in 12 | if let actualValue = try actualExpression.evaluate() { 13 | let message = ExpectationMessage 14 | .expectedCustomValueTo( 15 | "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))", 16 | "\(actualValue.count)" 17 | ) 18 | .appended(details: "Actual Value: \(stringify(actualValue))") 19 | 20 | let result = expectedValue == actualValue.count 21 | return PredicateResult(bool: result, message: message) 22 | } else { 23 | return PredicateResult(status: .fail, message: .fail("")) 24 | } 25 | } 26 | } 27 | 28 | /// A Nimble matcher that succeeds when the actual collection's count equals 29 | /// the expected value 30 | public func haveCount(_ expectedValue: Int) -> Predicate { 31 | return Predicate { actualExpression in 32 | if let actualValue = try actualExpression.evaluate() { 33 | let message = ExpectationMessage 34 | .expectedCustomValueTo( 35 | "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))", 36 | "\(actualValue.count)" 37 | ) 38 | .appended(details: "Actual Value: \(stringify(actualValue))") 39 | 40 | let result = expectedValue == actualValue.count 41 | return PredicateResult(bool: result, message: message) 42 | } else { 43 | return PredicateResult(status: .fail, message: .fail("")) 44 | } 45 | } 46 | } 47 | 48 | #if canImport(Darwin) 49 | extension NMBObjCMatcher { 50 | @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBMatcher { 51 | return NMBPredicate { actualExpression in 52 | let location = actualExpression.location 53 | let actualValue = try actualExpression.evaluate() 54 | if let value = actualValue as? NMBCollection { 55 | let expr = Expression(expression: ({ value as NMBCollection}), location: location) 56 | return try haveCount(expected.intValue).satisfies(expr).toObjectiveC() 57 | } 58 | 59 | let message: ExpectationMessage 60 | if let actualValue = actualValue { 61 | message = ExpectationMessage.expectedCustomValueTo( 62 | "get type of NSArray, NSSet, NSDictionary, or NSHashTable", 63 | "\(String(describing: type(of: actualValue)))" 64 | ) 65 | } else { 66 | message = ExpectationMessage 67 | .expectedActualValueTo("have a collection with count \(stringify(expected.intValue))") 68 | .appendedBeNilHint() 69 | } 70 | return NMBPredicateResult(status: .fail, message: message.toObjectiveC()) 71 | } 72 | } 73 | } 74 | #endif 75 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/Match.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual string satisfies the regular expression 4 | /// described by the expected string. 5 | public func match(_ expectedValue: String?) -> Predicate { 6 | return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in 7 | if let actual = try actualExpression.evaluate() { 8 | if let regexp = expectedValue { 9 | let bool = actual.range(of: regexp, options: .regularExpression) != nil 10 | return PredicateStatus(bool: bool) 11 | } 12 | } 13 | 14 | return .fail 15 | } 16 | } 17 | 18 | #if canImport(Darwin) 19 | 20 | extension NMBObjCMatcher { 21 | @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher { 22 | return NMBPredicate { actualExpression in 23 | let actual = actualExpression.cast { $0 as? String } 24 | return try match(expected.description).satisfies(actual).toObjectiveC() 25 | } 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/MatchError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual expression evaluates to an 4 | /// error from the specified case. 5 | /// 6 | /// Errors are tried to be compared by their implementation of Equatable, 7 | /// otherwise they fallback to comparison by _domain and _code. 8 | public func matchError(_ error: T) -> Predicate { 9 | return Predicate.define { actualExpression in 10 | let actualError = try actualExpression.evaluate() 11 | 12 | let failureMessage = FailureMessage() 13 | setFailureMessageForError( 14 | failureMessage, 15 | postfixMessageVerb: "match", 16 | actualError: actualError, 17 | error: error 18 | ) 19 | 20 | var matches = false 21 | if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) { 22 | matches = true 23 | } 24 | 25 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) 26 | } 27 | } 28 | 29 | /// A Nimble matcher that succeeds when the actual expression evaluates to an 30 | /// error from the specified case. 31 | /// 32 | /// Errors are tried to be compared by their implementation of Equatable, 33 | /// otherwise they fallback to comparision by _domain and _code. 34 | public func matchError(_ error: T) -> Predicate { 35 | return Predicate.define { actualExpression in 36 | let actualError = try actualExpression.evaluate() 37 | 38 | let failureMessage = FailureMessage() 39 | setFailureMessageForError( 40 | failureMessage, 41 | postfixMessageVerb: "match", 42 | actualError: actualError, 43 | error: error 44 | ) 45 | 46 | var matches = false 47 | if let actualError = actualError as? T, error == actualError { 48 | matches = true 49 | } 50 | 51 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) 52 | } 53 | } 54 | 55 | /// A Nimble matcher that succeeds when the actual expression evaluates to an 56 | /// error of the specified type 57 | public func matchError(_ errorType: T.Type) -> Predicate { 58 | return Predicate.define { actualExpression in 59 | let actualError = try actualExpression.evaluate() 60 | 61 | let failureMessage = FailureMessage() 62 | setFailureMessageForError( 63 | failureMessage, 64 | postfixMessageVerb: "match", 65 | actualError: actualError, 66 | errorType: errorType 67 | ) 68 | 69 | var matches = false 70 | if actualError as? T != nil { 71 | matches = true 72 | } 73 | 74 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage()) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift: -------------------------------------------------------------------------------- 1 | /// DEPRECATED: A convenience API to build matchers that don't need special negation 2 | /// behavior. The toNot() behavior is the negation of to(). 3 | /// 4 | /// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil 5 | /// values are received in an expectation. 6 | /// 7 | /// You may use this when implementing your own custom matchers. 8 | /// 9 | /// Use the Matcher protocol instead of this type to accept custom matchers as 10 | /// input parameters. 11 | /// @see allPass for an example that uses accepts other matchers as input. 12 | @available(*, deprecated, message: "Use to Predicate instead") 13 | public struct MatcherFunc: Matcher { 14 | public let matcher: (Expression, FailureMessage) throws -> Bool 15 | 16 | public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { 17 | self.matcher = matcher 18 | } 19 | 20 | public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { 21 | return try matcher(actualExpression, failureMessage) 22 | } 23 | 24 | public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { 25 | return try !matcher(actualExpression, failureMessage) 26 | } 27 | 28 | /// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one. 29 | /// Note: You should definitely spend the time to convert to the new api as soon as possible 30 | /// since this struct type is deprecated. 31 | public var predicate: Predicate { 32 | return Predicate.fromDeprecatedMatcher(self) 33 | } 34 | } 35 | 36 | /// DEPRECATED: A convenience API to build matchers that don't need special negation 37 | /// behavior. The toNot() behavior is the negation of to(). 38 | /// 39 | /// Unlike MatcherFunc, this will always fail if an expectation contains nil. 40 | /// This applies regardless of using to() or toNot(). 41 | /// 42 | /// You may use this when implementing your own custom matchers. 43 | /// 44 | /// Use the Matcher protocol instead of this type to accept custom matchers as 45 | /// input parameters. 46 | /// @see allPass for an example that uses accepts other matchers as input. 47 | @available(*, deprecated, message: "Use to Predicate instead") 48 | public struct NonNilMatcherFunc: Matcher { 49 | public let matcher: (Expression, FailureMessage) throws -> Bool 50 | 51 | public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) { 52 | self.matcher = matcher 53 | } 54 | 55 | public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { 56 | let pass = try matcher(actualExpression, failureMessage) 57 | if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { 58 | return false 59 | } 60 | return pass 61 | } 62 | 63 | public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { 64 | let pass = try !matcher(actualExpression, failureMessage) 65 | if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) { 66 | return false 67 | } 68 | return pass 69 | } 70 | 71 | internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool { 72 | if try actualExpression.evaluate() == nil { 73 | failureMessage.postfixActual = " (use beNil() to match nils)" 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | /// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one. 80 | /// Note: You should definitely spend the time to convert to the new api as soon as possible 81 | /// since this struct type is deprecated. 82 | public var predicate: Predicate { 83 | return Predicate.fromDeprecatedMatcher(self) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | // `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. 3 | #if canImport(Darwin) 4 | import CoreGraphics 5 | #endif 6 | 7 | /// Implement this protocol to implement a custom matcher for Swift 8 | @available(*, deprecated, message: "Use Predicate instead") 9 | public protocol Matcher { 10 | associatedtype ValueType 11 | func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool 12 | func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool 13 | } 14 | 15 | extension Matcher { 16 | var predicate: Predicate { 17 | return Predicate.fromDeprecatedMatcher(self) 18 | } 19 | 20 | var toClosure: (Expression, FailureMessage, Bool) throws -> Bool { 21 | return ({ expr, msg, expectedResult in 22 | if expectedResult { 23 | return try self.matches(expr, failureMessage: msg) 24 | } else { 25 | return try self.doesNotMatch(expr, failureMessage: msg) 26 | } 27 | }) 28 | } 29 | } 30 | 31 | #if canImport(Darwin) 32 | /// Objective-C interface to the Swift variant of Matcher. 33 | @objc public protocol NMBMatcher { 34 | func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool 35 | func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool 36 | } 37 | #endif 38 | 39 | /// Protocol for types that support contain() matcher. 40 | public protocol NMBContainer { 41 | func contains(_ anObject: Any) -> Bool 42 | } 43 | 44 | #if canImport(Darwin) 45 | // swiftlint:disable:next todo 46 | // FIXME: NSHashTable can not conform to NMBContainer since swift-DEVELOPMENT-SNAPSHOT-2016-04-25-a 47 | //extension NSHashTable : NMBContainer {} // Corelibs Foundation does not include this class yet 48 | #endif 49 | 50 | extension NSArray: NMBContainer {} 51 | extension NSSet: NMBContainer {} 52 | 53 | /// Protocol for types that support only beEmpty(), haveCount() matchers 54 | public protocol NMBCollection { 55 | var count: Int { get } 56 | } 57 | 58 | #if canImport(Darwin) 59 | extension NSHashTable: NMBCollection {} // Corelibs Foundation does not include these classes yet 60 | extension NSMapTable: NMBCollection {} 61 | #endif 62 | 63 | extension NSSet: NMBCollection {} 64 | extension NSIndexSet: NMBCollection {} 65 | extension NSDictionary: NMBCollection {} 66 | 67 | /// Protocol for types that support beginWith(), endWith(), beEmpty() matchers 68 | public protocol NMBOrderedCollection: NMBCollection { 69 | func object(at index: Int) -> Any 70 | } 71 | 72 | extension NSArray: NMBOrderedCollection {} 73 | 74 | public protocol NMBDoubleConvertible { 75 | var doubleValue: CDouble { get } 76 | } 77 | 78 | extension Double: NMBDoubleConvertible { 79 | public var doubleValue: CDouble { 80 | return self 81 | } 82 | } 83 | 84 | extension Float: NMBDoubleConvertible { 85 | public var doubleValue: CDouble { 86 | return CDouble(self) 87 | } 88 | } 89 | 90 | extension CGFloat: NMBDoubleConvertible { 91 | public var doubleValue: CDouble { 92 | return CDouble(self) 93 | } 94 | } 95 | 96 | extension NSNumber: NMBDoubleConvertible { 97 | } 98 | 99 | private let dateFormatter: DateFormatter = { 100 | let formatter = DateFormatter() 101 | formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSS" 102 | formatter.locale = Locale(identifier: "en_US_POSIX") 103 | 104 | return formatter 105 | }() 106 | 107 | extension Date: NMBDoubleConvertible { 108 | public var doubleValue: CDouble { 109 | return self.timeIntervalSinceReferenceDate 110 | } 111 | } 112 | 113 | extension NSDate: NMBDoubleConvertible { 114 | public var doubleValue: CDouble { 115 | return self.timeIntervalSinceReferenceDate 116 | } 117 | } 118 | 119 | extension Date: TestOutputStringConvertible { 120 | public var testDescription: String { 121 | return dateFormatter.string(from: self) 122 | } 123 | } 124 | 125 | extension NSDate: TestOutputStringConvertible { 126 | public var testDescription: String { 127 | return dateFormatter.string(from: Date(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)) 128 | } 129 | } 130 | 131 | /// Protocol for types to support beLessThan(), beLessThanOrEqualTo(), 132 | /// beGreaterThan(), beGreaterThanOrEqualTo(), and equal() matchers. 133 | /// 134 | /// Types that conform to Swift's Comparable protocol will work implicitly too 135 | #if canImport(Darwin) 136 | @objc public protocol NMBComparable { 137 | func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult 138 | } 139 | #else 140 | // This should become obsolete once Corelibs Foundation adds Comparable conformance to NSNumber 141 | public protocol NMBComparable { 142 | func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult 143 | } 144 | #endif 145 | 146 | extension NSNumber: NMBComparable { 147 | public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { 148 | // swiftlint:disable:next force_cast 149 | return compare(otherObject as! NSNumber) 150 | } 151 | } 152 | extension NSString: NMBComparable { 153 | public func NMB_compare(_ otherObject: NMBComparable!) -> ComparisonResult { 154 | // swiftlint:disable:next force_cast 155 | return compare(otherObject as! String) 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/PostNotification.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | internal class NotificationCollector { 4 | private(set) var observedNotifications: [Notification] 5 | private let notificationCenter: NotificationCenter 6 | #if canImport(Darwin) 7 | private var token: AnyObject? 8 | #else 9 | private var token: NSObjectProtocol? 10 | #endif 11 | 12 | required init(notificationCenter: NotificationCenter) { 13 | self.notificationCenter = notificationCenter 14 | self.observedNotifications = [] 15 | } 16 | 17 | func startObserving() { 18 | // swiftlint:disable:next line_length 19 | self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] notification in 20 | // linux-swift gets confused by .append(n) 21 | self?.observedNotifications.append(notification) 22 | } 23 | } 24 | 25 | deinit { 26 | #if canImport(Darwin) 27 | if let token = self.token { 28 | self.notificationCenter.removeObserver(token) 29 | } 30 | #else 31 | if let token = self.token as? AnyObject { 32 | self.notificationCenter.removeObserver(token) 33 | } 34 | #endif 35 | } 36 | } 37 | 38 | private let mainThread = pthread_self() 39 | 40 | public func postNotifications( 41 | _ notificationsMatcher: T, 42 | fromNotificationCenter center: NotificationCenter = .default) 43 | -> Predicate 44 | where T: Matcher, T.ValueType == [Notification] 45 | { 46 | _ = mainThread // Force lazy-loading of this value 47 | let collector = NotificationCollector(notificationCenter: center) 48 | collector.startObserving() 49 | var once: Bool = false 50 | 51 | return Predicate { actualExpression in 52 | let collectorNotificationsExpression = Expression(memoizedExpression: { _ in 53 | return collector.observedNotifications 54 | }, location: actualExpression.location, withoutCaching: true) 55 | 56 | assert(pthread_equal(mainThread, pthread_self()) != 0, "Only expecting closure to be evaluated on main thread.") 57 | if !once { 58 | once = true 59 | _ = try actualExpression.evaluate() 60 | } 61 | 62 | let failureMessage = FailureMessage() 63 | let match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage) 64 | if collector.observedNotifications.isEmpty { 65 | failureMessage.actualValue = "no notifications" 66 | } else { 67 | failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>" 68 | } 69 | return PredicateResult(bool: match, message: failureMessage.toExpectationMessage()) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value matches with all of the matchers 4 | /// provided in the variable list of matchers. 5 | public func satisfyAllOf(_ matchers: U...) -> Predicate 6 | where U: Matcher, U.ValueType == T { 7 | return satisfyAllOf(matchers.map { $0.predicate }) 8 | } 9 | 10 | internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate { 11 | return Predicate.define { actualExpression in 12 | var postfixMessages = [String]() 13 | var matches = true 14 | for predicate in predicates { 15 | let result = try predicate.satisfies(actualExpression) 16 | if result.toBoolean(expectation: .toNotMatch) { 17 | matches = false 18 | } 19 | postfixMessages.append("{\(result.message.expectedMessage)}") 20 | } 21 | 22 | var msg: ExpectationMessage 23 | if let actualValue = try actualExpression.evaluate() { 24 | msg = .expectedCustomValueTo( 25 | "match all of: " + postfixMessages.joined(separator: ", and "), 26 | "\(actualValue)" 27 | ) 28 | } else { 29 | msg = .expectedActualValueTo( 30 | "match all of: " + postfixMessages.joined(separator: ", and ") 31 | ) 32 | } 33 | 34 | return PredicateResult(bool: matches, message: msg) 35 | } 36 | } 37 | 38 | public func && (left: Predicate, right: Predicate) -> Predicate { 39 | return satisfyAllOf(left, right) 40 | } 41 | 42 | #if canImport(Darwin) 43 | extension NMBObjCMatcher { 44 | @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { 45 | return NMBPredicate { actualExpression in 46 | if matchers.isEmpty { 47 | return NMBPredicateResult( 48 | status: NMBPredicateStatus.fail, 49 | message: NMBExpectationMessage( 50 | fail: "satisfyAllOf must be called with at least one matcher" 51 | ) 52 | ) 53 | } 54 | 55 | var elementEvaluators = [Predicate]() 56 | for matcher in matchers { 57 | let elementEvaluator = Predicate { expression in 58 | if let predicate = matcher as? NMBPredicate { 59 | // swiftlint:disable:next line_length 60 | return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() 61 | } else { 62 | let failureMessage = FailureMessage() 63 | let success = matcher.matches( 64 | // swiftlint:disable:next force_try 65 | { try! expression.evaluate() }, 66 | failureMessage: failureMessage, 67 | location: actualExpression.location 68 | ) 69 | return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) 70 | } 71 | } 72 | 73 | elementEvaluators.append(elementEvaluator) 74 | } 75 | 76 | return try satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() 77 | } 78 | } 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// A Nimble matcher that succeeds when the actual value matches with any of the matchers 4 | /// provided in the variable list of matchers. 5 | public func satisfyAnyOf(_ matchers: U...) -> Predicate 6 | where U: Matcher, U.ValueType == T { 7 | return satisfyAnyOf(matchers.map { $0.predicate }) 8 | } 9 | 10 | internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate { 11 | return Predicate.define { actualExpression in 12 | var postfixMessages = [String]() 13 | var matches = false 14 | for predicate in predicates { 15 | let result = try predicate.satisfies(actualExpression) 16 | if result.toBoolean(expectation: .toMatch) { 17 | matches = true 18 | } 19 | postfixMessages.append("{\(result.message.expectedMessage)}") 20 | } 21 | 22 | var msg: ExpectationMessage 23 | if let actualValue = try actualExpression.evaluate() { 24 | msg = .expectedCustomValueTo( 25 | "match one of: " + postfixMessages.joined(separator: ", or "), 26 | "\(actualValue)" 27 | ) 28 | } else { 29 | msg = .expectedActualValueTo( 30 | "match one of: " + postfixMessages.joined(separator: ", or ") 31 | ) 32 | } 33 | 34 | return PredicateResult(bool: matches, message: msg) 35 | } 36 | } 37 | 38 | public func || (left: Predicate, right: Predicate) -> Predicate { 39 | return satisfyAnyOf(left, right) 40 | } 41 | 42 | public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate { 43 | return satisfyAnyOf(left, right) 44 | } 45 | 46 | public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate { 47 | return satisfyAnyOf(left, right) 48 | } 49 | 50 | #if canImport(Darwin) 51 | extension NMBObjCMatcher { 52 | @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate { 53 | return NMBPredicate { actualExpression in 54 | if matchers.isEmpty { 55 | return NMBPredicateResult( 56 | status: NMBPredicateStatus.fail, 57 | message: NMBExpectationMessage( 58 | fail: "satisfyAnyOf must be called with at least one matcher" 59 | ) 60 | ) 61 | } 62 | 63 | var elementEvaluators = [Predicate]() 64 | for matcher in matchers { 65 | let elementEvaluator = Predicate { expression in 66 | if let predicate = matcher as? NMBPredicate { 67 | // swiftlint:disable:next line_length 68 | return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift() 69 | } else { 70 | let failureMessage = FailureMessage() 71 | let success = matcher.matches( 72 | // swiftlint:disable:next force_try 73 | { try! expression.evaluate() }, 74 | failureMessage: failureMessage, 75 | location: actualExpression.location 76 | ) 77 | return PredicateResult(bool: success, message: failureMessage.toExpectationMessage()) 78 | } 79 | } 80 | 81 | elementEvaluators.append(elementEvaluator) 82 | } 83 | 84 | return try satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC() 85 | } 86 | } 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public func throwAssertion() -> Predicate { 4 | return Predicate { actualExpression in 5 | #if arch(x86_64) && canImport(Darwin) && !SWIFT_PACKAGE 6 | let message = ExpectationMessage.expectedTo("throw an assertion") 7 | 8 | var actualError: Error? 9 | let caughtException: BadInstructionException? = catchBadInstruction { 10 | #if os(tvOS) 11 | if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning { 12 | print() 13 | print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " + 14 | "fatal error while using throwAssertion(), please disable 'Debug Executable' " + 15 | "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " + 16 | "'Debug Executable'. If you've already done that, suppress this warning " + 17 | "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " + 18 | "This is required because the standard methods of catching assertions " + 19 | "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " + 20 | "debugger uses is the fallback method for tvOS." 21 | ) 22 | print() 23 | NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true 24 | } 25 | #endif 26 | do { 27 | try actualExpression.evaluate() 28 | } catch { 29 | actualError = error 30 | } 31 | } 32 | 33 | if let actualError = actualError { 34 | return PredicateResult( 35 | bool: false, 36 | message: message.appended(message: "; threw error instead <\(actualError)>") 37 | ) 38 | } else { 39 | return PredicateResult(bool: caughtException != nil, message: message) 40 | } 41 | #elseif SWIFT_PACKAGE 42 | fatalError("The throwAssertion Nimble matcher does not currently support Swift CLI." + 43 | " You can silence this error by placing the test case inside an #if !SWIFT_PACKAGE" + 44 | " conditional statement") 45 | #else 46 | fatalError("The throwAssertion Nimble matcher can only run on x86_64 platforms with " + 47 | "Objective-C (e.g. macOS, iPhone 5s or later simulators). You can silence this error " + 48 | "by placing the test case inside an #if arch(x86_64) or canImport(Darwin) conditional statement") 49 | #endif 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Matchers/ToSucceed.swift: -------------------------------------------------------------------------------- 1 | /** 2 | Used by the `toSucceed` matcher. 3 | 4 | This is the return type for the closure. 5 | */ 6 | public enum ToSucceedResult { 7 | case succeeded 8 | case failed(reason: String) 9 | } 10 | 11 | /** 12 | A Nimble matcher that takes in a closure for validation. 13 | 14 | Return `.succeeded` when the validation succeeds. 15 | Return `.failed` with a failure reason when the validation fails. 16 | */ 17 | public func succeed() -> Predicate<() -> ToSucceedResult> { 18 | return Predicate.define { actualExpression in 19 | let optActual = try actualExpression.evaluate() 20 | guard let actual = optActual else { 21 | return PredicateResult(status: .fail, message: .fail("expected a closure, got ")) 22 | } 23 | 24 | switch actual() { 25 | case .succeeded: 26 | return PredicateResult( 27 | bool: true, 28 | message: .expectedCustomValueTo("succeed", "") 29 | ) 30 | case .failed(let reason): 31 | return PredicateResult( 32 | bool: false, 33 | message: .expectedCustomValueTo("succeed", " because <\(reason)>") 34 | ) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Nimble.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "NMBExceptionCapture.h" 3 | #import "NMBStringify.h" 4 | #import "DSL.h" 5 | 6 | #if TARGET_OS_TV 7 | #import "CwlPreconditionTesting_POSIX.h" 8 | #else 9 | #import "CwlPreconditionTesting.h" 10 | #endif 11 | 12 | FOUNDATION_EXPORT double NimbleVersionNumber; 13 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; 14 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Utils/Errors.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Generic 4 | 5 | internal func setFailureMessageForError( 6 | _ failureMessage: FailureMessage, 7 | postfixMessageVerb: String = "throw", 8 | actualError: Error?, 9 | error: T? = nil, 10 | errorType: T.Type? = nil, 11 | closure: ((T) -> Void)? = nil) { 12 | failureMessage.postfixMessage = "\(postfixMessageVerb) error" 13 | 14 | if let error = error { 15 | failureMessage.postfixMessage += " <\(error)>" 16 | } else if errorType != nil || closure != nil { 17 | failureMessage.postfixMessage += " from type <\(T.self)>" 18 | } 19 | if closure != nil { 20 | failureMessage.postfixMessage += " that satisfies block" 21 | } 22 | if error == nil && errorType == nil && closure == nil { 23 | failureMessage.postfixMessage = "\(postfixMessageVerb) any error" 24 | } 25 | 26 | if let actualError = actualError { 27 | failureMessage.actualValue = "<\(actualError)>" 28 | } else { 29 | failureMessage.actualValue = "no error" 30 | } 31 | } 32 | 33 | internal func errorMatchesExpectedError( 34 | _ actualError: Error, 35 | expectedError: T) -> Bool { 36 | return actualError._domain == expectedError._domain 37 | && actualError._code == expectedError._code 38 | } 39 | 40 | // Non-generic 41 | 42 | internal func setFailureMessageForError( 43 | _ failureMessage: FailureMessage, 44 | actualError: Error?, 45 | closure: ((Error) -> Void)?) { 46 | failureMessage.postfixMessage = "throw error" 47 | 48 | if closure != nil { 49 | failureMessage.postfixMessage += " that satisfies block" 50 | } else { 51 | failureMessage.postfixMessage = "throw any error" 52 | } 53 | 54 | if let actualError = actualError { 55 | failureMessage.actualValue = "<\(actualError)>" 56 | } else { 57 | failureMessage.actualValue = "no error" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Utils/Functional.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if !swift(>=4.2) 4 | extension Sequence { 5 | internal func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool { 6 | for item in self { 7 | if try !predicate(item) { 8 | return false 9 | } 10 | } 11 | return true 12 | } 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Ideally we would always use `StaticString` as the type for tracking the file name 4 | // that expectations originate from, for consistency with `assert` etc. from the 5 | // stdlib, and because recent versions of the XCTest overlay require `StaticString` 6 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we 7 | // have to use `String` instead because StaticString can't be generated from Objective-C 8 | #if SWIFT_PACKAGE 9 | public typealias FileString = StaticString 10 | #else 11 | public typealias FileString = String 12 | #endif 13 | 14 | public final class SourceLocation: NSObject { 15 | public let file: FileString 16 | public let line: UInt 17 | 18 | override init() { 19 | file = "Unknown File" 20 | line = 0 21 | } 22 | 23 | init(file: FileString, line: UInt) { 24 | self.file = file 25 | self.line = line 26 | } 27 | 28 | override public var description: String { 29 | return "\(file):\(line)" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface NMBExceptionCapture : NSObject 5 | 6 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally; 7 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); 8 | 9 | @end 10 | 11 | typedef void(^NMBSourceCallbackBlock)(BOOL successful); 12 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m: -------------------------------------------------------------------------------- 1 | #import "NMBExceptionCapture.h" 2 | 3 | @interface NMBExceptionCapture () 4 | @property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable); 5 | @property (nonatomic, copy) void(^ _Nullable finally)(void); 6 | @end 7 | 8 | @implementation NMBExceptionCapture 9 | 10 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally { 11 | self = [super init]; 12 | if (self) { 13 | self.handler = handler; 14 | self.finally = finally; 15 | } 16 | return self; 17 | } 18 | 19 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock { 20 | @try { 21 | unsafeBlock(); 22 | } 23 | @catch (NSException *exception) { 24 | if (self.handler) { 25 | self.handler(exception); 26 | } 27 | } 28 | @finally { 29 | if (self.finally) { 30 | self.finally(); 31 | } 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h: -------------------------------------------------------------------------------- 1 | @class NSString; 2 | 3 | /** 4 | * Returns a string appropriate for displaying in test output 5 | * from the provided value. 6 | * 7 | * @param anyObject A value that will show up in a test's output. 8 | * 9 | * @return The string that is returned can be 10 | * customized per type by conforming a type to the `TestOutputStringConvertible` 11 | * protocol. When stringifying a non-`TestOutputStringConvertible` type, this 12 | * function will return the value's debug description and then its 13 | * normal description if available and in that order. Otherwise it 14 | * will return the result of constructing a string from the value. 15 | * 16 | * @see `TestOutputStringConvertible` 17 | */ 18 | extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result)); 19 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m: -------------------------------------------------------------------------------- 1 | #import "NMBStringify.h" 2 | 3 | #if __has_include("Nimble-Swift.h") 4 | #import "Nimble-Swift.h" 5 | #else 6 | #import 7 | #endif 8 | 9 | NSString *_Nonnull NMBStringify(id _Nullable anyObject) { 10 | return [NMBStringer stringify:anyObject]; 11 | } 12 | -------------------------------------------------------------------------------- /Example/Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #if __has_include("Nimble-Swift.h") 5 | #import "Nimble-Swift.h" 6 | #else 7 | #import 8 | #endif 9 | 10 | #pragma mark - Method Swizzling 11 | 12 | /// Swaps the implementations between two instance methods. 13 | /// 14 | /// @param class The class containing `originalSelector`. 15 | /// @param originalSelector Original method to replace. 16 | /// @param replacementSelector Replacement method. 17 | void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) { 18 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 19 | Method replacementMethod = class_getInstanceMethod(class, replacementSelector); 20 | 21 | BOOL didAddMethod = 22 | class_addMethod(class, 23 | originalSelector, 24 | method_getImplementation(replacementMethod), 25 | method_getTypeEncoding(replacementMethod)); 26 | 27 | if (didAddMethod) { 28 | class_replaceMethod(class, 29 | replacementSelector, 30 | method_getImplementation(originalMethod), 31 | method_getTypeEncoding(originalMethod)); 32 | } else { 33 | method_exchangeImplementations(originalMethod, replacementMethod); 34 | } 35 | } 36 | 37 | #pragma mark - Private 38 | 39 | @interface XCTestObservationCenter (Private) 40 | - (void)_addLegacyTestObserver:(id)observer; 41 | @end 42 | 43 | @implementation XCTestObservationCenter (Register) 44 | 45 | /// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary 46 | /// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early 47 | /// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output. 48 | /// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer, 49 | /// falling back to registering after the first normal observer if this private method ever changes. 50 | + (void)load { 51 | if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) { 52 | // Swizzle -_addLegacyTestObserver: 53 | swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:)); 54 | } else { 55 | // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented 56 | swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:)); 57 | } 58 | } 59 | 60 | #pragma mark - Replacement Methods 61 | 62 | /// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. 63 | - (void)NMB_original__addLegacyTestObserver:(id)observer { 64 | [self NMB_original__addLegacyTestObserver:observer]; 65 | 66 | static dispatch_once_t onceToken; 67 | dispatch_once(&onceToken, ^{ 68 | [self addTestObserver:[CurrentTestCaseTracker sharedInstance]]; 69 | }); 70 | } 71 | 72 | /// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added. 73 | /// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3) 74 | - (void)NMB_original_addTestObserver:(id)observer { 75 | [self NMB_original_addTestObserver:observer]; 76 | 77 | static dispatch_once_t onceToken; 78 | dispatch_once(&onceToken, ^{ 79 | [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]]; 80 | }); 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Example/Pods/Quick/README.md: -------------------------------------------------------------------------------- 1 | ![](http://f.cl.ly/items/0r1E192C1R0b2g2Q3h2w/QuickLogo_Color.png) 2 | 3 | [![Build Status](https://travis-ci.org/Quick/Quick.svg?branch=master)](https://travis-ci.org/Quick/Quick) 4 | [![CocoaPods](https://img.shields.io/cocoapods/v/Quick.svg)](https://cocoapods.org/pods/Quick) 5 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Platforms](https://img.shields.io/cocoapods/p/Quick.svg)](https://cocoapods.org/pods/Quick) 7 | [![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) 8 | 9 | Quick is a behavior-driven development framework for Swift and Objective-C. 10 | Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo). 11 | 12 | ![](https://raw.githubusercontent.com/Quick/Assets/master/Screenshots/QuickSpec%20screenshot.png) 13 | 14 | ```swift 15 | // Swift 16 | 17 | import Quick 18 | import Nimble 19 | 20 | class TableOfContentsSpec: QuickSpec { 21 | override func spec() { 22 | describe("the 'Documentation' directory") { 23 | it("has everything you need to get started") { 24 | let sections = Directory("Documentation").sections 25 | expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups")) 26 | expect(sections).to(contain("Installing Quick")) 27 | } 28 | 29 | context("if it doesn't have what you're looking for") { 30 | it("needs to be updated") { 31 | let you = You(awesome: true) 32 | expect{you.submittedAnIssue}.toEventually(beTruthy()) 33 | } 34 | } 35 | } 36 | } 37 | } 38 | ``` 39 | #### Nimble 40 | Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md). 41 | 42 | ## Swift Version 43 | 44 | Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project. 45 | 46 | |Swift version |Quick version |Nimble version | 47 | |:--------------------|:---------------|:--------------| 48 | |Swift 4.2 |v1.3.2 or later |v7.3.2 or later| 49 | |Swift 3 / Swift 4 |v1.0.0 or later |v5.0.0 or later| 50 | |Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 | 51 | 52 | ## Documentation 53 | 54 | All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile: 55 | 56 | ```rb 57 | # Podfile 58 | 59 | use_frameworks! 60 | 61 | target "MyApp" do 62 | # Normal libraries 63 | 64 | abstract_target 'Tests' do 65 | inherit! :search_paths 66 | target "MyAppTests" 67 | target "MyAppUITests" 68 | 69 | pod 'Quick' 70 | pod 'Nimble' 71 | end 72 | end 73 | ``` 74 | 75 | ## Projects using Quick 76 | 77 | Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them. 78 | 79 | Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick). 80 | 81 | ## Who uses Quick 82 | 83 | Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses? 84 | 85 | Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick). 86 | 87 | 88 | ## License 89 | 90 | Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details. 91 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Behavior.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` function with a context instance of the generic type. 3 | */ 4 | 5 | open class Behavior { 6 | 7 | public static var name: String { return String(describing: self) } 8 | /** 9 | override this method in your behavior to define a set of reusable examples. 10 | 11 | This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach` 12 | and `afterEach` closures, as well as any number of examples (defined using `it`). 13 | 14 | - parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject. 15 | */ 16 | open class func spec(_ aContext: @escaping () -> Context) {} 17 | } 18 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Callsite.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) && !SWIFT_PACKAGE 4 | @objcMembers 5 | public class _CallsiteBase: NSObject {} 6 | #else 7 | public class _CallsiteBase: NSObject {} 8 | #endif 9 | 10 | // Ideally we would always use `StaticString` as the type for tracking the file name 11 | // in which an example is defined, for consistency with `assert` etc. from the 12 | // stdlib, and because recent versions of the XCTest overlay require `StaticString` 13 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on macOS), we 14 | // have to use `String` instead because StaticString can't be generated from Objective-C 15 | #if SWIFT_PACKAGE 16 | public typealias FileString = StaticString 17 | #else 18 | public typealias FileString = String 19 | #endif 20 | 21 | /** 22 | An object encapsulating the file and line number at which 23 | a particular example is defined. 24 | */ 25 | final public class Callsite: _CallsiteBase { 26 | /** 27 | The absolute path of the file in which an example is defined. 28 | */ 29 | public let file: FileString 30 | 31 | /** 32 | The line number on which an example is defined. 33 | */ 34 | public let line: UInt 35 | 36 | internal init(file: FileString, line: UInt) { 37 | self.file = file 38 | self.line = line 39 | } 40 | } 41 | 42 | extension Callsite { 43 | /** 44 | Returns a boolean indicating whether two Callsite objects are equal. 45 | If two callsites are in the same file and on the same line, they must be equal. 46 | */ 47 | @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool { 48 | return String(describing: lhs.file) == String(describing: rhs.file) && lhs.line == rhs.line 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/ErrorUtility.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | internal func raiseError(_ message: String) -> Never { 4 | #if canImport(Darwin) 5 | NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise() 6 | #endif 7 | 8 | // This won't be reached when ObjC is available and the exception above is raisd 9 | fatalError(message) 10 | } 11 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Example.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private var numberOfExamplesRun = 0 4 | private var numberOfIncludedExamples = 0 5 | 6 | #if canImport(Darwin) && !SWIFT_PACKAGE 7 | @objcMembers 8 | public class _ExampleBase: NSObject {} 9 | #else 10 | public class _ExampleBase: NSObject {} 11 | #endif 12 | 13 | /** 14 | Examples, defined with the `it` function, use assertions to 15 | demonstrate how code should behave. These are like "tests" in XCTest. 16 | */ 17 | final public class Example: _ExampleBase { 18 | /** 19 | A boolean indicating whether the example is a shared example; 20 | i.e.: whether it is an example defined with `itBehavesLike`. 21 | */ 22 | public var isSharedExample = false 23 | 24 | /** 25 | The site at which the example is defined. 26 | This must be set correctly in order for Xcode to highlight 27 | the correct line in red when reporting a failure. 28 | */ 29 | public var callsite: Callsite 30 | 31 | weak internal var group: ExampleGroup? 32 | 33 | private let internalDescription: String 34 | private let closure: () -> Void 35 | private let flags: FilterFlags 36 | 37 | internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: @escaping () -> Void) { 38 | self.internalDescription = description 39 | self.closure = closure 40 | self.callsite = callsite 41 | self.flags = flags 42 | } 43 | 44 | public override var description: String { 45 | return internalDescription 46 | } 47 | 48 | /** 49 | The example name. A name is a concatenation of the name of 50 | the example group the example belongs to, followed by the 51 | description of the example itself. 52 | 53 | The example name is used to generate a test method selector 54 | to be displayed in Xcode's test navigator. 55 | */ 56 | public var name: String { 57 | guard let groupName = group?.name else { return description } 58 | return "\(groupName), \(description)" 59 | } 60 | 61 | /** 62 | Executes the example closure, as well as all before and after 63 | closures defined in the its surrounding example groups. 64 | */ 65 | public func run() { 66 | let world = World.sharedWorld 67 | 68 | if numberOfIncludedExamples == 0 { 69 | numberOfIncludedExamples = world.includedExampleCount 70 | } 71 | 72 | if numberOfExamplesRun == 0 { 73 | world.suiteHooks.executeBefores() 74 | } 75 | 76 | let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun) 77 | world.currentExampleMetadata = exampleMetadata 78 | defer { 79 | world.currentExampleMetadata = nil 80 | } 81 | 82 | world.exampleHooks.executeBefores(exampleMetadata) 83 | group!.phase = .beforesExecuting 84 | for before in group!.befores { 85 | before(exampleMetadata) 86 | } 87 | group!.phase = .beforesFinished 88 | 89 | closure() 90 | 91 | group!.phase = .aftersExecuting 92 | for after in group!.afters { 93 | after(exampleMetadata) 94 | } 95 | group!.phase = .aftersFinished 96 | world.exampleHooks.executeAfters(exampleMetadata) 97 | 98 | numberOfExamplesRun += 1 99 | 100 | if !world.isRunningAdditionalSuites && numberOfExamplesRun >= numberOfIncludedExamples { 101 | world.suiteHooks.executeAfters() 102 | } 103 | } 104 | 105 | /** 106 | Evaluates the filter flags set on this example and on the example groups 107 | this example belongs to. Flags set on the example are trumped by flags on 108 | the example group it belongs to. Flags on inner example groups are trumped 109 | by flags on outer example groups. 110 | */ 111 | internal var filterFlags: FilterFlags { 112 | var aggregateFlags = flags 113 | for (key, value) in group!.filterFlags { 114 | aggregateFlags[key] = value 115 | } 116 | return aggregateFlags 117 | } 118 | } 119 | 120 | extension Example { 121 | /** 122 | Returns a boolean indicating whether two Example objects are equal. 123 | If two examples are defined at the exact same callsite, they must be equal. 124 | */ 125 | @nonobjc public static func == (lhs: Example, rhs: Example) -> Bool { 126 | return lhs.callsite == rhs.callsite 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/ExampleGroup.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /** 4 | Example groups are logical groupings of examples, defined with 5 | the `describe` and `context` functions. Example groups can share 6 | setup and teardown code. 7 | */ 8 | final public class ExampleGroup: NSObject { 9 | weak internal var parent: ExampleGroup? 10 | internal let hooks = ExampleHooks() 11 | 12 | internal var phase: HooksPhase = .nothingExecuted 13 | 14 | private let internalDescription: String 15 | private let flags: FilterFlags 16 | private let isInternalRootExampleGroup: Bool 17 | private var childGroups = [ExampleGroup]() 18 | private var childExamples = [Example]() 19 | 20 | internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) { 21 | self.internalDescription = description 22 | self.flags = flags 23 | self.isInternalRootExampleGroup = isInternalRootExampleGroup 24 | } 25 | 26 | public override var description: String { 27 | return internalDescription 28 | } 29 | 30 | /** 31 | Returns a list of examples that belong to this example group, 32 | or to any of its descendant example groups. 33 | */ 34 | public var examples: [Example] { 35 | return childExamples + childGroups.flatMap { $0.examples } 36 | } 37 | 38 | internal var name: String? { 39 | guard let parent = parent else { 40 | return isInternalRootExampleGroup ? nil : description 41 | } 42 | 43 | guard let name = parent.name else { return description } 44 | return "\(name), \(description)" 45 | } 46 | 47 | internal var filterFlags: FilterFlags { 48 | var aggregateFlags = flags 49 | walkUp { group in 50 | for (key, value) in group.flags { 51 | aggregateFlags[key] = value 52 | } 53 | } 54 | return aggregateFlags 55 | } 56 | 57 | internal var befores: [BeforeExampleWithMetadataClosure] { 58 | var closures = Array(hooks.befores.reversed()) 59 | walkUp { group in 60 | closures.append(contentsOf: Array(group.hooks.befores.reversed())) 61 | } 62 | return Array(closures.reversed()) 63 | } 64 | 65 | internal var afters: [AfterExampleWithMetadataClosure] { 66 | var closures = hooks.afters 67 | walkUp { group in 68 | closures.append(contentsOf: group.hooks.afters) 69 | } 70 | return closures 71 | } 72 | 73 | internal func walkDownExamples(_ callback: (_ example: Example) -> Void) { 74 | for example in childExamples { 75 | callback(example) 76 | } 77 | for group in childGroups { 78 | group.walkDownExamples(callback) 79 | } 80 | } 81 | 82 | internal func appendExampleGroup(_ group: ExampleGroup) { 83 | group.parent = self 84 | childGroups.append(group) 85 | } 86 | 87 | internal func appendExample(_ example: Example) { 88 | example.group = self 89 | childExamples.append(example) 90 | } 91 | 92 | private func walkUp(_ callback: (_ group: ExampleGroup) -> Void) { 93 | var group = self 94 | while let parent = group.parent { 95 | callback(parent) 96 | group = parent 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/ExampleMetadata.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) && !SWIFT_PACKAGE 4 | @objcMembers 5 | public class _ExampleMetadataBase: NSObject {} 6 | #else 7 | public class _ExampleMetadataBase: NSObject {} 8 | #endif 9 | 10 | /** 11 | A class that encapsulates information about an example, 12 | including the index at which the example was executed, as 13 | well as the example itself. 14 | */ 15 | final public class ExampleMetadata: _ExampleMetadataBase { 16 | /** 17 | The example for which this metadata was collected. 18 | */ 19 | public let example: Example 20 | 21 | /** 22 | The index at which this example was executed in the 23 | test suite. 24 | */ 25 | public let exampleIndex: Int 26 | 27 | internal init(example: Example, exampleIndex: Int) { 28 | self.example = example 29 | self.exampleIndex = exampleIndex 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Filter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | #if canImport(Darwin) && !SWIFT_PACKAGE 4 | @objcMembers 5 | public class _FilterBase: NSObject {} 6 | #else 7 | public class _FilterBase: NSObject {} 8 | #endif 9 | 10 | /** 11 | A mapping of string keys to booleans that can be used to 12 | filter examples or example groups. For example, a "focused" 13 | example would have the flags [Focused: true]. 14 | */ 15 | public typealias FilterFlags = [String: Bool] 16 | 17 | /** 18 | A namespace for filter flag keys, defined primarily to make the 19 | keys available in Objective-C. 20 | */ 21 | final public class Filter: _FilterBase { 22 | /** 23 | Example and example groups with [Focused: true] are included in test runs, 24 | excluding all other examples without this flag. Use this to only run one or 25 | two tests that you're currently focusing on. 26 | */ 27 | public class var focused: String { 28 | return "focused" 29 | } 30 | 31 | /** 32 | Example and example groups with [Pending: true] are excluded from test runs. 33 | Use this to temporarily suspend examples that you know do not pass yet. 34 | */ 35 | public class var pending: String { 36 | return "pending" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Hooks/Closures.swift: -------------------------------------------------------------------------------- 1 | // MARK: Example Hooks 2 | 3 | /** 4 | A closure executed before an example is run. 5 | */ 6 | public typealias BeforeExampleClosure = () -> Void 7 | 8 | /** 9 | A closure executed before an example is run. The closure is given example metadata, 10 | which contains information about the example that is about to be run. 11 | */ 12 | public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void 13 | 14 | /** 15 | A closure executed after an example is run. 16 | */ 17 | public typealias AfterExampleClosure = BeforeExampleClosure 18 | 19 | /** 20 | A closure executed after an example is run. The closure is given example metadata, 21 | which contains information about the example that has just finished running. 22 | */ 23 | public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure 24 | 25 | // MARK: Suite Hooks 26 | 27 | /** 28 | A closure executed before any examples are run. 29 | */ 30 | public typealias BeforeSuiteClosure = () -> Void 31 | 32 | /** 33 | A closure executed after all examples have finished running. 34 | */ 35 | public typealias AfterSuiteClosure = BeforeSuiteClosure 36 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after each example. 3 | */ 4 | final internal class ExampleHooks { 5 | internal var befores: [BeforeExampleWithMetadataClosure] = [] 6 | internal var afters: [AfterExampleWithMetadataClosure] = [] 7 | internal var phase: HooksPhase = .nothingExecuted 8 | 9 | internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) { 10 | befores.append(closure) 11 | } 12 | 13 | internal func appendBefore(_ closure: @escaping BeforeExampleClosure) { 14 | befores.append { (_: ExampleMetadata) in closure() } 15 | } 16 | 17 | internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) { 18 | afters.append(closure) 19 | } 20 | 21 | internal func appendAfter(_ closure: @escaping AfterExampleClosure) { 22 | afters.append { (_: ExampleMetadata) in closure() } 23 | } 24 | 25 | internal func executeBefores(_ exampleMetadata: ExampleMetadata) { 26 | phase = .beforesExecuting 27 | for before in befores { 28 | before(exampleMetadata) 29 | } 30 | 31 | phase = .beforesFinished 32 | } 33 | 34 | internal func executeAfters(_ exampleMetadata: ExampleMetadata) { 35 | phase = .aftersExecuting 36 | for after in afters { 37 | after(exampleMetadata) 38 | } 39 | 40 | phase = .aftersFinished 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A description of the execution cycle of the current example with 3 | respect to the hooks of that example. 4 | */ 5 | internal enum HooksPhase { 6 | case nothingExecuted 7 | case beforesExecuting 8 | case beforesFinished 9 | case aftersExecuting 10 | case aftersFinished 11 | } 12 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift: -------------------------------------------------------------------------------- 1 | /** 2 | A container for closures to be executed before and after all examples. 3 | */ 4 | final internal class SuiteHooks { 5 | internal var befores: [BeforeSuiteClosure] = [] 6 | internal var afters: [AfterSuiteClosure] = [] 7 | internal var phase: HooksPhase = .nothingExecuted 8 | 9 | internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) { 10 | befores.append(closure) 11 | } 12 | 13 | internal func appendAfter(_ closure: @escaping AfterSuiteClosure) { 14 | afters.append(closure) 15 | } 16 | 17 | internal func executeBefores() { 18 | phase = .beforesExecuting 19 | for before in befores { 20 | before() 21 | } 22 | phase = .beforesFinished 23 | } 24 | 25 | internal func executeAfters() { 26 | phase = .aftersExecuting 27 | for after in afters { 28 | after() 29 | } 30 | phase = .aftersFinished 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | 3 | import Foundation 4 | 5 | extension Bundle { 6 | 7 | /** 8 | Locates the first bundle with a '.xctest' file extension. 9 | */ 10 | internal static var currentTestBundle: Bundle? { 11 | return allBundles.first { $0.bundlePath.hasSuffix(".xctest") } 12 | } 13 | 14 | /** 15 | Return the module name of the bundle. 16 | Uses the bundle filename and transform it to match Xcode's transformation. 17 | Module name has to be a valid "C99 extended identifier". 18 | */ 19 | internal var moduleName: String { 20 | let fileName = bundleURL.fileName 21 | return fileName.c99ExtendedIdentifier 22 | } 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | import Foundation 3 | 4 | /** 5 | Responsible for building a "Selected tests" suite. This corresponds to a single 6 | spec, and all its examples. 7 | */ 8 | internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder { 9 | 10 | /** 11 | The test spec class to run. 12 | */ 13 | let testCaseClass: AnyClass! 14 | 15 | /** 16 | For Objective-C classes, returns the class name. For Swift classes without, 17 | an explicit Objective-C name, returns a module-namespaced class name 18 | (e.g., "FooTests.FooSpec"). 19 | */ 20 | var testSuiteClassName: String { 21 | return NSStringFromClass(testCaseClass) 22 | } 23 | 24 | /** 25 | Given a test case name: 26 | 27 | FooSpec/testFoo 28 | 29 | Optionally constructs a test suite builder for the named test case class 30 | in the running test bundle. 31 | 32 | If no test bundle can be found, or the test case class can't be found, 33 | initialization fails and returns `nil`. 34 | */ 35 | init?(forTestCaseWithName name: String) { 36 | guard let testCaseClass = testCaseClassForTestCaseWithName(name) else { 37 | self.testCaseClass = nil 38 | return nil 39 | } 40 | 41 | self.testCaseClass = testCaseClass 42 | } 43 | 44 | /** 45 | Returns a `QuickTestSuite` that runs the associated test case class. 46 | */ 47 | func buildTestSuite() -> QuickTestSuite { 48 | return QuickTestSuite(forTestCaseClass: testCaseClass) 49 | } 50 | 51 | } 52 | 53 | /** 54 | Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named 55 | test case class in that bundle. 56 | 57 | Returns `nil` if a bundle or test case class cannot be found. 58 | */ 59 | private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? { 60 | func extractClassName(_ name: String) -> String? { 61 | return name.components(separatedBy: "/").first 62 | } 63 | 64 | guard let className = extractClassName(name) else { return nil } 65 | guard let bundle = Bundle.currentTestBundle else { return nil } 66 | 67 | if let testCaseClass = bundle.classNamed(className) { return testCaseClass } 68 | 69 | let moduleName = bundle.moduleName 70 | 71 | return NSClassFromString("\(moduleName).\(className)") 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/QuickTestSuite.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | 3 | import XCTest 4 | 5 | /** 6 | This protocol defines the role of an object that builds test suites. 7 | */ 8 | internal protocol QuickTestSuiteBuilder { 9 | 10 | /** 11 | Construct a `QuickTestSuite` instance with the appropriate test cases added as tests. 12 | 13 | Subsequent calls to this method should return equivalent test suites. 14 | */ 15 | func buildTestSuite() -> QuickTestSuite 16 | 17 | } 18 | 19 | /** 20 | A base class for a class cluster of Quick test suites, that should correctly 21 | build dynamic test suites for XCTest to execute. 22 | */ 23 | public class QuickTestSuite: XCTestSuite { 24 | 25 | private static var builtTestSuites: Set = Set() 26 | 27 | /** 28 | Construct a test suite for a specific, selected subset of test cases (rather 29 | than the default, which as all test cases). 30 | 31 | If this method is called multiple times for the same test case class, e.g.. 32 | 33 | FooSpec/testFoo 34 | FooSpec/testBar 35 | 36 | It is expected that the first call should return a valid test suite, and 37 | all subsequent calls should return `nil`. 38 | */ 39 | @objc 40 | public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { 41 | guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } 42 | 43 | let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName) 44 | if inserted { 45 | return builder.buildTestSuite() 46 | } else { 47 | return nil 48 | } 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/String+C99ExtendedIdentifier.swift: -------------------------------------------------------------------------------- 1 | #if canImport(Darwin) 2 | import Foundation 3 | 4 | extension String { 5 | private static var invalidCharacters: CharacterSet = { 6 | var invalidCharacters = CharacterSet() 7 | 8 | let invalidCharacterSets: [CharacterSet] = [ 9 | .whitespacesAndNewlines, 10 | .illegalCharacters, 11 | .controlCharacters, 12 | .punctuationCharacters, 13 | .nonBaseCharacters, 14 | .symbols 15 | ] 16 | 17 | for invalidSet in invalidCharacterSets { 18 | invalidCharacters.formUnion(invalidSet) 19 | } 20 | 21 | return invalidCharacters 22 | }() 23 | 24 | internal var c99ExtendedIdentifier: String { 25 | let validComponents = components(separatedBy: String.invalidCharacters) 26 | let result = validComponents.joined(separator: "_") 27 | 28 | return result.isEmpty ? "_" : result 29 | } 30 | } 31 | 32 | /// Extension methods or properties for NSObject subclasses are invisible from 33 | /// the Objective-C runtime on static linking unless the consumers add `-ObjC` 34 | /// linker flag, so let's make a wrapper class to mitigate that situation. 35 | /// 36 | /// See: https://github.com/Quick/Quick/issues/785 and https://github.com/Quick/Quick/pull/803 37 | @objc 38 | class QCKObjCStringUtils: NSObject { 39 | override private init() {} 40 | 41 | @objc 42 | static func c99ExtendedIdentifier(from string: String) -> String { 43 | return string.c99ExtendedIdentifier 44 | } 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/Quick/URL+FileName.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension URL { 4 | 5 | /** 6 | Returns the path file name without file extension. 7 | */ 8 | var fileName: String { 9 | return self.deletingPathExtension().lastPathComponent 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class Configuration; 4 | 5 | /** 6 | Subclass QuickConfiguration and override the +[QuickConfiguration configure:] 7 | method in order to configure how Quick behaves when running specs, or to define 8 | shared examples that are used across spec files. 9 | */ 10 | @interface QuickConfiguration : NSObject 11 | 12 | /** 13 | This method is executed on each subclass of this class before Quick runs 14 | any examples. You may override this method on as many subclasses as you like, but 15 | there is no guarantee as to the order in which these methods are executed. 16 | 17 | You can override this method in order to: 18 | 19 | 1. Configure how Quick behaves, by modifying properties on the Configuration object. 20 | Setting the same properties in several methods has undefined behavior. 21 | 22 | 2. Define shared examples using `sharedExamples`. 23 | 24 | @param configuration A mutable object that is used to configure how Quick behaves on 25 | a framework level. For details on all the options, see the 26 | documentation in Configuration.swift. 27 | */ 28 | + (void)configure:(Configuration *)configuration; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m: -------------------------------------------------------------------------------- 1 | #import "QuickConfiguration.h" 2 | #import 3 | 4 | #if __has_include("Quick-Swift.h") 5 | #import "Quick-Swift.h" 6 | #else 7 | #import 8 | #endif 9 | 10 | typedef void (^QCKClassEnumerationBlock)(Class klass); 11 | 12 | /** 13 | Finds all direct subclasses of the given class and passes them to the block provided. 14 | The classes are iterated over in the order that objc_getClassList returns them. 15 | 16 | @param klass The base class to find subclasses of. 17 | @param block A block that takes a Class. This block will be executed once for each subclass of klass. 18 | */ 19 | void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) { 20 | Class *classes = NULL; 21 | int classesCount = objc_getClassList(NULL, 0); 22 | 23 | if (classesCount > 0) { 24 | classes = (Class *)calloc(sizeof(Class), classesCount); 25 | classesCount = objc_getClassList(classes, classesCount); 26 | 27 | Class subclass, superclass; 28 | for(int i = 0; i < classesCount; i++) { 29 | subclass = classes[i]; 30 | superclass = class_getSuperclass(subclass); 31 | if (superclass == klass && block) { 32 | block(subclass); 33 | } 34 | } 35 | 36 | free(classes); 37 | } 38 | } 39 | 40 | @implementation QuickConfiguration 41 | 42 | #pragma mark - Object Lifecycle 43 | 44 | /** 45 | QuickConfiguration is not meant to be instantiated; it merely provides a hook 46 | for users to configure how Quick behaves. Raise an exception if an instance of 47 | QuickConfiguration is created. 48 | */ 49 | - (instancetype)init { 50 | NSString *className = NSStringFromClass([self class]); 51 | NSString *selectorName = NSStringFromSelector(@selector(configure:)); 52 | [NSException raise:NSInternalInconsistencyException 53 | format:@"%@ is not meant to be instantiated; " 54 | @"subclass %@ and override %@ to configure Quick.", 55 | className, className, selectorName]; 56 | return nil; 57 | } 58 | 59 | #pragma mark - NSObject Overrides 60 | 61 | /** 62 | Hook into when QuickConfiguration is initialized in the runtime in order to 63 | call +[QuickConfiguration configure:] on each of its subclasses. 64 | */ 65 | + (void)initialize { 66 | // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses. 67 | if ([self class] == [QuickConfiguration class]) { 68 | 69 | // Only enumerate over subclasses once, even if +[QuickConfiguration initialize] 70 | // were to be called several times. This is necessary because +[QuickSpec initialize] 71 | // manually calls +[QuickConfiguration initialize]. 72 | static dispatch_once_t onceToken; 73 | dispatch_once(&onceToken, ^{ 74 | qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) { 75 | [[World sharedWorld] configure:^(Configuration *configuration) { 76 | [klass configure:configuration]; 77 | }]; 78 | }); 79 | [[World sharedWorld] finalizeConfiguration]; 80 | }); 81 | } 82 | } 83 | 84 | #pragma mark - Public Interface 85 | 86 | + (void)configure:(Configuration *)configuration { } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m: -------------------------------------------------------------------------------- 1 | #import "QCKDSL.h" 2 | 3 | #if __has_include("Quick-Swift.h") 4 | #import "Quick-Swift.h" 5 | #else 6 | #import 7 | #endif 8 | 9 | void qck_beforeSuite(QCKDSLEmptyBlock closure) { 10 | [[World sharedWorld] beforeSuite:closure]; 11 | } 12 | 13 | void qck_afterSuite(QCKDSLEmptyBlock closure) { 14 | [[World sharedWorld] afterSuite:closure]; 15 | } 16 | 17 | void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) { 18 | [[World sharedWorld] sharedExamples:name closure:closure]; 19 | } 20 | 21 | void qck_describe(NSString *description, QCKDSLEmptyBlock closure) { 22 | [[World sharedWorld] describe:description flags:@{} closure:closure]; 23 | } 24 | 25 | void qck_context(NSString *description, QCKDSLEmptyBlock closure) { 26 | qck_describe(description, closure); 27 | } 28 | 29 | void qck_beforeEach(QCKDSLEmptyBlock closure) { 30 | [[World sharedWorld] beforeEach:closure]; 31 | } 32 | 33 | void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) { 34 | [[World sharedWorld] beforeEachWithMetadata:closure]; 35 | } 36 | 37 | void qck_afterEach(QCKDSLEmptyBlock closure) { 38 | [[World sharedWorld] afterEach:closure]; 39 | } 40 | 41 | void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) { 42 | [[World sharedWorld] afterEachWithMetadata:closure]; 43 | } 44 | 45 | QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) { 46 | return ^(NSString *description, QCKDSLEmptyBlock closure) { 47 | [[World sharedWorld] itWithDescription:description 48 | flags:flags 49 | file:file 50 | line:line 51 | closure:closure]; 52 | }; 53 | } 54 | 55 | QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) { 56 | return ^(NSString *name, QCKDSLSharedExampleContext context) { 57 | [[World sharedWorld] itBehavesLikeSharedExampleNamed:name 58 | sharedExampleContext:context 59 | flags:flags 60 | file:file 61 | line:line]; 62 | }; 63 | } 64 | 65 | void qck_pending(NSString *description, QCKDSLEmptyBlock closure) { 66 | [[World sharedWorld] pending:description closure:closure]; 67 | } 68 | 69 | void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) { 70 | [[World sharedWorld] xdescribe:description flags:@{} closure:closure]; 71 | } 72 | 73 | void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) { 74 | qck_xdescribe(description, closure); 75 | } 76 | 77 | void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) { 78 | [[World sharedWorld] fdescribe:description flags:@{} closure:closure]; 79 | } 80 | 81 | void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) { 82 | qck_fdescribe(description, closure); 83 | } 84 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/Quick.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Quick. 4 | FOUNDATION_EXPORT double QuickVersionNumber; 5 | 6 | //! Project version string for Quick. 7 | FOUNDATION_EXPORT const unsigned char QuickVersionString[]; 8 | 9 | #import "QuickSpec.h" 10 | #import "QCKDSL.h" 11 | #import "QuickConfiguration.h" 12 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /** 4 | QuickSpec is a base class all specs written in Quick inherit from. 5 | They need to inherit from QuickSpec, a subclass of XCTestCase, in 6 | order to be discovered by the XCTest framework. 7 | 8 | XCTest automatically compiles a list of XCTestCase subclasses included 9 | in the test target. It iterates over each class in that list, and creates 10 | a new instance of that class for each test method. It then creates an 11 | "invocation" to execute that test method. The invocation is an instance of 12 | NSInvocation, which represents a single message send in Objective-C. 13 | The invocation is set on the XCTestCase instance, and the test is run. 14 | 15 | Most of the code in QuickSpec is dedicated to hooking into XCTest events. 16 | First, when the spec is first loaded and before it is sent any messages, 17 | the +[NSObject initialize] method is called. QuickSpec overrides this method 18 | to call +[QuickSpec spec]. This builds the example group stacks and 19 | registers them with Quick.World, a global register of examples. 20 | 21 | Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest 22 | automatically finds all methods whose selectors begin with the string "test". 23 | However, QuickSpec overrides this default behavior by implementing the 24 | +[XCTestCase testInvocations] method. This method iterates over each example 25 | registered in Quick.World, defines a new method for that example, and 26 | returns an invocation to call that method to XCTest. Those invocations are 27 | the tests that are run by XCTest. Their selector names are displayed in 28 | the Xcode test navigation bar. 29 | */ 30 | @interface QuickSpec : XCTestCase 31 | 32 | /** 33 | Override this method in your spec to define a set of example groups 34 | and examples. 35 | 36 | @code 37 | override func spec() { 38 | describe("winter") { 39 | it("is coming") { 40 | // ... 41 | } 42 | } 43 | } 44 | @endcode 45 | 46 | See DSL.swift for more information on what syntax is available. 47 | */ 48 | - (void)spec; 49 | 50 | /** 51 | Returns the currently executing spec. Use in specs that require XCTestCase 52 | methods, e.g. expectationWithDescription. 53 | */ 54 | @property (class, nonatomic, readonly) QuickSpec *current; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #if __has_include("Quick-Swift.h") 5 | #import "Quick-Swift.h" 6 | #else 7 | #import 8 | #endif 9 | 10 | @interface XCTestSuite (QuickTestSuiteBuilder) 11 | @end 12 | 13 | @implementation XCTestSuite (QuickTestSuiteBuilder) 14 | 15 | /** 16 | In order to ensure we can correctly build dynamic test suites, we need to 17 | replace some of the default test suite constructors. 18 | */ 19 | + (void)load { 20 | Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:)); 21 | Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:)); 22 | method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName); 23 | } 24 | 25 | /** 26 | The `+testSuiteForTestCaseWithName:` method is called when a specific test case 27 | class is run from the Xcode test navigator. If the built test suite is `nil`, 28 | Xcode will not run any tests for that test case. 29 | 30 | Given if the following test case class is run from the Xcode test navigator: 31 | 32 | FooSpec 33 | testFoo 34 | testBar 35 | 36 | XCTest will invoke this once per test case, with test case names following this format: 37 | 38 | FooSpec/testFoo 39 | FooSpec/testBar 40 | */ 41 | + (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name { 42 | return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m: -------------------------------------------------------------------------------- 1 | #import "QuickSpecBase.h" 2 | 3 | #pragma mark - _QuickSelectorWrapper 4 | 5 | @interface _QuickSelectorWrapper () 6 | @property(nonatomic, assign) SEL selector; 7 | @end 8 | 9 | @implementation _QuickSelectorWrapper 10 | 11 | - (instancetype)initWithSelector:(SEL)selector { 12 | self = [super init]; 13 | _selector = selector; 14 | return self; 15 | } 16 | 17 | @end 18 | 19 | 20 | #pragma mark - _QuickSpecBase 21 | 22 | @implementation _QuickSpecBase 23 | 24 | - (instancetype)init { 25 | self = [super initWithInvocation: nil]; 26 | return self; 27 | } 28 | 29 | /** 30 | Invocations for each test method in the test case. QuickSpec overrides this method to define a 31 | new method for each example defined in +[QuickSpec spec]. 32 | 33 | @return An array of invocations that execute the newly defined example methods. 34 | */ 35 | + (NSArray *)testInvocations { 36 | NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors]; 37 | NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:wrappers.count]; 38 | 39 | for (_QuickSelectorWrapper *wrapper in wrappers) { 40 | SEL selector = wrapper.selector; 41 | NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector]; 42 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; 43 | invocation.selector = selector; 44 | 45 | [invocations addObject:invocation]; 46 | } 47 | 48 | return invocations; 49 | } 50 | 51 | + (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors { 52 | return @[]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Example/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface _QuickSelectorWrapper : NSObject 5 | - (instancetype)initWithSelector:(SEL)selector; 6 | @end 7 | 8 | @interface _QuickSpecBase : XCTestCase 9 | + (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors; 10 | - (instancetype)init NS_DESIGNATED_INITIALIZER; 11 | @end 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Chirp : NSObject 3 | @end 4 | @implementation PodsDummy_Chirp 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double ChirpVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char ChirpVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp.modulemap: -------------------------------------------------------------------------------- 1 | framework module Chirp { 2 | umbrella header "Chirp-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Chirp.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Chirp 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/ResourceBundle-Chirp-Chirp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.1.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Chirp/ResourceBundle-Chirp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.1.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 7.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 8.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Nimble : NSObject 3 | @end 4 | @implementation PodsDummy_Nimble 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "Nimble.h" 14 | #import "DSL.h" 15 | #import "NMBExceptionCapture.h" 16 | #import "NMBStringify.h" 17 | #import "CwlCatchException.h" 18 | #import "CwlMachBadInstructionHandler.h" 19 | #import "mach_excServer.h" 20 | #import "CwlPreconditionTesting.h" 21 | 22 | FOUNDATION_EXPORT double NimbleVersionNumber; 23 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble.modulemap: -------------------------------------------------------------------------------- 1 | framework module Nimble { 2 | umbrella header "Nimble-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Nimble/Nimble.xcconfig: -------------------------------------------------------------------------------- 1 | APPLICATION_EXTENSION_API_ONLY = YES 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Nimble 3 | ENABLE_BITCODE = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -weak-lswiftXCTest -weak_framework "XCTest" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS $(inherited) -suppress-warnings 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nimble 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Chirp 5 | 6 | Copyright (c) 2016 JP McGlone 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2016 JP McGlone <jp@trifl.co> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Chirp 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Chirp_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Chirp_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Chirp_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Chirp_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp/Chirp.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Chirp" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Chirp_Example { 2 | umbrella header "Pods-Chirp_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Example/Pods-Chirp_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp/Chirp.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Chirp" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Chirp_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Chirp_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Chirp_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Chirp_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/Chirp" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp/Chirp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Chirp" -framework "Nimble" -framework "Quick" -framework "XCTest" -weak_framework "XCTest" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Chirp_Tests { 2 | umbrella header "Pods-Chirp_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Chirp_Tests/Pods-Chirp_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/Chirp" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Chirp/Chirp.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers" 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_LDFLAGS = $(inherited) -framework "Chirp" -framework "Nimble" -framework "Quick" -framework "XCTest" -weak_framework "XCTest" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Quick : NSObject 3 | @end 4 | @implementation PodsDummy_Quick 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "QuickConfiguration.h" 14 | #import "QCKDSL.h" 15 | #import "Quick.h" 16 | #import "QuickSpec.h" 17 | 18 | FOUNDATION_EXPORT double QuickVersionNumber; 19 | FOUNDATION_EXPORT const unsigned char QuickVersionString[]; 20 | 21 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick.modulemap: -------------------------------------------------------------------------------- 1 | framework module Quick { 2 | umbrella header "Quick-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Quick/Quick.xcconfig: -------------------------------------------------------------------------------- 1 | APPLICATION_EXTENSION_API_ONLY = YES 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Quick 3 | ENABLE_BITCODE = NO 4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" 5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 6 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -framework "XCTest" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Quick 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | // https://github.com/Quick/Quick 2 | 3 | import Quick 4 | import Nimble 5 | import Chirp 6 | 7 | class TableOfContentsSpec: QuickSpec { 8 | override func spec() { 9 | describe("Chirp") { 10 | describe("when prepare sound") { 11 | context("and the file exists") { 12 | beforeEach { 13 | Chirp.sharedManager.prepareSound(fileName: "test.mp3") 14 | } 15 | 16 | afterEach { 17 | Chirp.sharedManager.removeSound(fileName: "test.mp3") 18 | } 19 | 20 | it("should have sound in cache") { 21 | let keyExists = Chirp.sharedManager.sounds["test.mp3"] != nil 22 | expect(keyExists) == true 23 | } 24 | 25 | describe("when removing sound") { 26 | beforeEach { 27 | Chirp.sharedManager.removeSound(fileName: "test.mp3") 28 | } 29 | 30 | it("should not have sound in cache") { 31 | let keyExists = Chirp.sharedManager.sounds["test.mp3"] != nil 32 | expect(keyExists) == false 33 | } 34 | } 35 | 36 | describe("when removing a sound once but preparing twice") { 37 | beforeEach { 38 | Chirp.sharedManager.prepareSound(fileName: "test.mp3") 39 | Chirp.sharedManager.removeSound(fileName: "test.mp3") 40 | } 41 | 42 | it("should have sound in cache with count 1") { 43 | let keyExists = Chirp.sharedManager.sounds["test.mp3"] != nil 44 | expect(keyExists) == true 45 | expect(Chirp.sharedManager.sounds["test.mp3"]?.count) == 1 46 | } 47 | } 48 | } 49 | 50 | context("and the file doesn't exist") { 51 | beforeEach { 52 | Chirp.sharedManager.prepareSound(fileName: "test2") 53 | } 54 | 55 | afterEach { 56 | Chirp.sharedManager.removeSound(fileName: "test2") 57 | } 58 | 59 | it("should not have sound in cache") { 60 | let keyExists = Chirp.sharedManager.sounds["test2"] != nil 61 | expect(keyExists) == false 62 | } 63 | } 64 | } 65 | 66 | describe("when play sound without prepare") { 67 | context("and the file exists") { 68 | beforeEach { 69 | Chirp.sharedManager.playSound(fileName: "test.mp3") 70 | } 71 | 72 | it("should not have sound in cache") { 73 | let keyExists = Chirp.sharedManager.sounds["test.mp3"] != nil 74 | expect(keyExists) == false 75 | } 76 | } 77 | } 78 | 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Example/Tests/test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trifl/Chirp/e55ea0f134cb9975f8f9bd72310cc8589cc2b26d/Example/Tests/test.mp3 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 JP McGlone 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trifl/Chirp/e55ea0f134cb9975f8f9bd72310cc8589cc2b26d/Pod/Assets/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trifl/Chirp/e55ea0f134cb9975f8f9bd72310cc8589cc2b26d/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/Chirp.swift: -------------------------------------------------------------------------------- 1 | import AVFoundation 2 | 3 | open class Chirp { 4 | open class Sound { 5 | open var id: SystemSoundID 6 | open fileprivate(set) var count: Int = 1 7 | init(id: SystemSoundID) { 8 | self.id = id 9 | } 10 | } 11 | 12 | // MARK: - Constants 13 | fileprivate let kDefaultExtension = "wav" 14 | 15 | // MARK: - Singleton 16 | public static let sharedManager = Chirp() 17 | 18 | // MARK: - Private Variables 19 | open fileprivate(set) var sounds = [String:Sound]() 20 | 21 | // MARK: - Public 22 | @discardableResult 23 | open func prepareSound(fileName: String) -> String? { 24 | let fixedSoundFileName = self.fixedSoundFileName(fileName: fileName) 25 | if let sound = soundForKey(fixedSoundFileName) { 26 | sound.count += 1 27 | return fixedSoundFileName 28 | } 29 | 30 | if let pathURL = pathURLForSound(fileName: fixedSoundFileName) { 31 | var soundID: SystemSoundID = 0 32 | AudioServicesCreateSystemSoundID(pathURL as CFURL, &soundID) 33 | let sound = Sound(id: soundID) 34 | sounds[fixedSoundFileName] = sound 35 | return fixedSoundFileName 36 | } 37 | 38 | return nil 39 | } 40 | 41 | open func playSound(fileName: String) { 42 | let fixedSoundFileName = self.fixedSoundFileName(fileName: fileName) 43 | if let sound = soundForKey(fixedSoundFileName) { 44 | AudioServicesPlaySystemSound(sound.id) 45 | } 46 | } 47 | 48 | open func removeSound(fileName: String) { 49 | let fixedSoundFileName = self.fixedSoundFileName(fileName: fileName) 50 | if let sound = soundForKey(fixedSoundFileName) { 51 | sound.count -= 1 52 | if sound.count <= 0 { 53 | AudioServicesDisposeSystemSoundID(sound.id) 54 | sounds.removeValue(forKey: fixedSoundFileName) 55 | } 56 | } 57 | } 58 | 59 | // MARK: - Private 60 | fileprivate func soundForKey(_ key: String) -> Sound? { 61 | return sounds[key] 62 | } 63 | 64 | fileprivate func fixedSoundFileName(fileName: String) -> String { 65 | var fixedSoundFileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines) 66 | var soundFileComponents = fixedSoundFileName.components(separatedBy: ".") 67 | if soundFileComponents.count == 1 { 68 | fixedSoundFileName = "\(soundFileComponents[0]).\(kDefaultExtension)" 69 | } 70 | return fixedSoundFileName 71 | } 72 | 73 | fileprivate func pathForSound(fileName: String) -> String? { 74 | let fixedSoundFileName = self.fixedSoundFileName(fileName: fileName) 75 | let components = fixedSoundFileName.components(separatedBy: ".") 76 | return Bundle.main.path(forResource: components[0], ofType: components[1]) 77 | } 78 | 79 | fileprivate func pathURLForSound(fileName: String) -> URL? { 80 | if let path = pathForSound(fileName: fileName) { 81 | return URL(fileURLWithPath: path) 82 | } 83 | return nil 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chirp 2 | 3 | The easiest way to prepare, play, and remove sounds in your Swift app! 4 | 5 | ##Installation 6 | ###CocoaPods Installation 7 | Chirp is available on CocoaPods. Just add the following to your project Podfile: 8 | 9 | ``` 10 | pod 'Chirp', '~> 1.2' 11 | ``` 12 | 13 | ###Non-CocoaPods Installation 14 | You can drop Chirp.swift directly into your project, or drag the Chirp project into your workspace. 15 | 16 | ### Sample code 17 | `prepareSound` is used to preload a sound into memory. This increases the retain count of the sound by 1. You must call this method before calling playSound 18 | ```swift 19 | /* MyViewController.swift */ 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | // Load sounds into memory 25 | Chirp.sharedManager.prepareSound("boop") // default extension is .wav 26 | Chirp.sharedManager.prepareSound("ding.mp3") // so other extensions you must name explicitly 27 | } 28 | ``` 29 | 30 | `playSound` plays the preloaded sound 31 | ```swift 32 | func submitButtonTouched(button: UIButton) { 33 | // Since the sound is already loaded into memory, this will play immediately 34 | Chirp.sharedManager.playSound("boop") 35 | 36 | // example function that might get called when you touch a button 37 | submitForm() 38 | } 39 | ``` 40 | 41 | `removeSound` removes the sound from memory 42 | ```swift 43 | deinit { 44 | // Cleanup is really simple! 45 | Chirp.sharedManager.removeSound("boop") 46 | Chirp.sharedManager.removeSound("ding.mp3") 47 | Chirp.sharedManager.removeSound("oops.mp3") 48 | 49 | // If you never loaded the sounds, e.g. viewDidLoad wasn't called, or submission never failed or succeeded, 50 | // that's ok, because these will function as no-ops 51 | } 52 | ``` 53 | 54 | Enjoy! I know sound management can be a little annoying. Hopefully this helps your project out a little bit. 55 | --------------------------------------------------------------------------------