Camera automated build and test framework.
This commit is contained in:
parent
19074490ac
commit
db46f2b744
10
Podfile
10
Podfile
|
|
@ -1,3 +1,9 @@
|
|||
platform :ios, '7.1'
|
||||
|
||||
pod 'CameraManager', :git => 'https://gist.github.com/2204678.git'
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
|
||||
target 'cameraTests' do
|
||||
use_frameworks!
|
||||
pod 'Quick', :git => 'https://github.com/Quick/Quick.git', :commit => 'f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea'
|
||||
pod 'Nimble', :git => 'https://github.com/Quick/Nimble.git', :commit => '9538a301d5320fd607f01c931dc282868b0e827a'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
PODS:
|
||||
- Nimble (0.3.0)
|
||||
- Quick (0.2.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Nimble (from `https://github.com/Quick/Nimble.git`, commit `9538a301d5320fd607f01c931dc282868b0e827a`)
|
||||
- Quick (from `https://github.com/Quick/Quick.git`, commit `f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Nimble:
|
||||
:commit: 9538a301d5320fd607f01c931dc282868b0e827a
|
||||
:git: https://github.com/Quick/Nimble.git
|
||||
Quick:
|
||||
:commit: f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea
|
||||
:git: https://github.com/Quick/Quick.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
Nimble:
|
||||
:commit: 9538a301d5320fd607f01c931dc282868b0e827a
|
||||
:git: https://github.com/Quick/Nimble.git
|
||||
Quick:
|
||||
:commit: f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea
|
||||
:git: https://github.com/Quick/Quick.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Nimble: 55fef248ef3703024ce431db817160ad24d89ba3
|
||||
Quick: 1bda8b4c8d43f6b4dd69ca001918b1767b3c9c93
|
||||
|
||||
COCOAPODS: 0.36.0
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/objc/DSL.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/objc/NMBExceptionCapture.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/Nimble.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/NSString+QCKSelectorName.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/DSL/QCKDSL.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/Quick.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/Configuration/QuickConfiguration.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/QuickSpec.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/objc/DSL.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/objc/NMBExceptionCapture.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Nimble/Nimble/Nimble.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/NSString+QCKSelectorName.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/DSL/QCKDSL.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/Quick.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/Configuration/QuickConfiguration.h
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../../Quick/Quick/QuickSpec.h
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "Nimble",
|
||||
"version": "0.3.0",
|
||||
"summary": "A Matcher Framework for Swift and Objective-C",
|
||||
"description": " Use Nimble to express the expected outcomes of Swift or Objective-C expressions. Inspired by Cedar.\n",
|
||||
"homepage": "https://github.com/Quick/Nimble",
|
||||
"license": {
|
||||
"type": "Apache 2.0",
|
||||
"file": "LICENSE.md"
|
||||
},
|
||||
"authors": "Quick Contributors",
|
||||
"platforms": {
|
||||
"ios": "8.0",
|
||||
"osx": "10.10"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/Quick/Nimble.git",
|
||||
"tag": "v0.3.0"
|
||||
},
|
||||
"source_files": [
|
||||
"Nimble",
|
||||
"Nimble/**/*.{swift,h,m}"
|
||||
],
|
||||
"frameworks": "XCTest",
|
||||
"requires_arc": true
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "Quick",
|
||||
"version": "0.2.2",
|
||||
"summary": "The Swift (and Objective-C) testing framework.",
|
||||
"description": " Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo.\n",
|
||||
"homepage": "https://github.com/Quick/Quick",
|
||||
"license": {
|
||||
"type": "Apache 2.0",
|
||||
"file": "LICENSE"
|
||||
},
|
||||
"authors": "Quick Contributors",
|
||||
"platforms": {
|
||||
"ios": "8.0",
|
||||
"osx": "10.10"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/Quick/Quick.git",
|
||||
"tag": "v0.2.2"
|
||||
},
|
||||
"source_files": [
|
||||
"Quick",
|
||||
"Quick/**/*.{swift,h,m}"
|
||||
],
|
||||
"frameworks": "XCTest",
|
||||
"requires_arc": true
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
PODS:
|
||||
- Nimble (0.3.0)
|
||||
- Quick (0.2.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Nimble (from `https://github.com/Quick/Nimble.git`, commit `9538a301d5320fd607f01c931dc282868b0e827a`)
|
||||
- Quick (from `https://github.com/Quick/Quick.git`, commit `f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Nimble:
|
||||
:commit: 9538a301d5320fd607f01c931dc282868b0e827a
|
||||
:git: https://github.com/Quick/Nimble.git
|
||||
Quick:
|
||||
:commit: f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea
|
||||
:git: https://github.com/Quick/Quick.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
Nimble:
|
||||
:commit: 9538a301d5320fd607f01c931dc282868b0e827a
|
||||
:git: https://github.com/Quick/Nimble.git
|
||||
Quick:
|
||||
:commit: f8c9ff9f499fc5ea72ff55c1c5eed32e1ff303ea
|
||||
:git: https://github.com/Quick/Quick.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Nimble: 55fef248ef3703024ce431db817160ad24d89ba3
|
||||
Quick: 1bda8b4c8d43f6b4dd69ca001918b1767b3c9c93
|
||||
|
||||
COCOAPODS: 0.36.0
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Quick Team
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import Foundation
|
||||
|
||||
/// Protocol for the assertion handler that Nimble uses for all expectations.
|
||||
public protocol AssertionHandler {
|
||||
func assert(assertion: Bool, message: String, location: SourceLocation)
|
||||
}
|
||||
|
||||
/// Global backing interface for assertions that Nimble creates.
|
||||
/// Defaults to a private test handler that passes through to XCTest.
|
||||
///
|
||||
/// @see AssertionHandler
|
||||
var CurrentAssertionHandler: AssertionHandler = XCTestHandler()
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import Foundation
|
||||
|
||||
/// A data structure that stores information about an assertion when
|
||||
/// AssertionRecorder is set as the Nimble assertion handler.
|
||||
///
|
||||
/// @see AssertionRecorder
|
||||
/// @see AssertionHandler
|
||||
public struct AssertionRecord {
|
||||
/// Whether the assertion succeeded or failed
|
||||
public let success: Bool
|
||||
/// The failure message the assertion would display on failure.
|
||||
public let message: String
|
||||
/// The source location the expectation occurred on.
|
||||
public let location: SourceLocation
|
||||
}
|
||||
|
||||
/// An AssertionHandler that silently records assertions that Nimble makes.
|
||||
/// This is useful for testing failure messages for matchers.
|
||||
///
|
||||
/// @see AssertionHandler
|
||||
public class AssertionRecorder : AssertionHandler {
|
||||
/// All the assertions that were captured by this recorder
|
||||
public var assertions = [AssertionRecord]()
|
||||
|
||||
public init() {}
|
||||
|
||||
public func assert(assertion: Bool, message: String, location: SourceLocation) {
|
||||
assertions.append(
|
||||
AssertionRecord(
|
||||
success: assertion,
|
||||
message: message,
|
||||
location: location))
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows you to temporarily replace the current Nimble assertion handler with
|
||||
/// the one provided for the scope of the closure.
|
||||
///
|
||||
/// Once the closure finishes, then the original Nimble assertion handler is restored.
|
||||
///
|
||||
/// @see AssertionHandler
|
||||
public func withAssertionHandler(tempAssertionHandler: AssertionHandler, closure: () -> Void) {
|
||||
let oldRecorder = CurrentAssertionHandler
|
||||
let capturer = NMBExceptionCapture(handler: nil, finally: ({
|
||||
CurrentAssertionHandler = oldRecorder
|
||||
}))
|
||||
CurrentAssertionHandler = tempAssertionHandler
|
||||
capturer.tryBlock {
|
||||
closure()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
class XCTestHandler : AssertionHandler {
|
||||
func assert(assertion: Bool, message: String, location: SourceLocation) {
|
||||
if !assertion {
|
||||
XCTFail(message, file: location.file, line: location.line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import Foundation
|
||||
|
||||
/// Only classes, protocols, methods, properties, and subscript declarations can be
|
||||
/// bridges to Objective-C via the @objc keyword. This class encapsulates callback-style
|
||||
/// asynchronous waiting logic so that it may be called from Objective-C and Swift.
|
||||
@objc public class NMBWait {
|
||||
public class func until(#timeout: NSTimeInterval, action: (() -> Void) -> Void, file: String = __FILE__, line: UInt = __LINE__) -> Void {
|
||||
var completed = false
|
||||
var token: dispatch_once_t = 0
|
||||
let result = pollBlock(pollInterval: 0.01, timeoutInterval: timeout) {
|
||||
dispatch_once(&token) {
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
action() { completed = true }
|
||||
}
|
||||
}
|
||||
return completed
|
||||
}
|
||||
if result == PollResult.Failure {
|
||||
let pluralize = (timeout == 1 ? "" : "s")
|
||||
fail("Waited more than \(timeout) second\(pluralize)", file: file, line: line)
|
||||
} else if result == PollResult.Timeout {
|
||||
fail("Stall on main thread - too much enqueued on main run loop before waitUntil executes.", file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
public class func until(action: (() -> Void) -> Void, file: String = __FILE__, line: UInt = __LINE__) -> Void {
|
||||
until(timeout: 1, action: action, file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait asynchronously until the done closure is called.
|
||||
///
|
||||
/// This will advance the run loop.
|
||||
public func waitUntil(#timeout: NSTimeInterval, action: (() -> Void) -> Void, file: String = __FILE__, line: UInt = __LINE__) -> Void {
|
||||
NMBWait.until(timeout: timeout, action: action, file: file, line: line)
|
||||
}
|
||||
|
||||
/// Wait asynchronously until the done closure is called.
|
||||
///
|
||||
/// This will advance the run loop.
|
||||
public func waitUntil(action: (() -> Void) -> Void, file: String = __FILE__, line: UInt = __LINE__) -> Void {
|
||||
NMBWait.until(action, file: file, line: line)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/// Make an expectation on a given actual value. The value given is lazily evaluated.
|
||||
public func expect<T>(expression: @autoclosure () -> T?, file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression,
|
||||
location: SourceLocation(file: file, line: line)))
|
||||
}
|
||||
|
||||
/// Make an expectation on a given actual value. The closure is lazily invoked.
|
||||
public func expect<T>(file: String = __FILE__, line: UInt = __LINE__, expression: () -> T?) -> Expectation<T> {
|
||||
return Expectation(
|
||||
expression: Expression(
|
||||
expression: expression,
|
||||
location: SourceLocation(file: file, line: line)))
|
||||
}
|
||||
|
||||
/// Always fails the test with a message and a specified location.
|
||||
public func fail(message: String, #location: SourceLocation) {
|
||||
CurrentAssertionHandler.assert(false, message: message, location: location)
|
||||
}
|
||||
|
||||
/// Always fails the test with a message.
|
||||
public func fail(message: String, file: String = __FILE__, line: UInt = __LINE__) {
|
||||
fail(message, location: SourceLocation(file: file, line: line))
|
||||
}
|
||||
|
||||
/// Always fails the test.
|
||||
public func fail(file: String = __FILE__, line: UInt = __LINE__) {
|
||||
fail("fail() always fails")
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import Foundation
|
||||
|
||||
public struct Expectation<T> {
|
||||
let expression: Expression<T>
|
||||
|
||||
public func verify(pass: Bool, _ message: String) {
|
||||
CurrentAssertionHandler.assert(pass, message: message, location: expression.location)
|
||||
}
|
||||
|
||||
public func to<U where U: Matcher, U.ValueType == T>(matcher: U) {
|
||||
var msg = FailureMessage()
|
||||
let pass = matcher.matches(expression, failureMessage: msg)
|
||||
if msg.actualValue == "" {
|
||||
msg.actualValue = "<\(stringify(expression.evaluate()))>"
|
||||
}
|
||||
verify(pass, msg.stringValue())
|
||||
}
|
||||
|
||||
public func toNot<U where U: Matcher, U.ValueType == T>(matcher: U) {
|
||||
var msg = FailureMessage()
|
||||
let pass = matcher.doesNotMatch(expression, failureMessage: msg)
|
||||
if msg.actualValue == "" {
|
||||
msg.actualValue = "<\(stringify(expression.evaluate()))>"
|
||||
}
|
||||
verify(pass, msg.stringValue())
|
||||
}
|
||||
|
||||
public func notTo<U where U: Matcher, U.ValueType == T>(matcher: U) {
|
||||
toNot(matcher)
|
||||
}
|
||||
|
||||
// see:
|
||||
// - BasicMatcherWrapper for extension
|
||||
// - AsyncMatcherWrapper for extension
|
||||
// - NonNilMatcherWrapper for extension
|
||||
//
|
||||
// - NMBExpectation for Objective-C interface
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import Foundation
|
||||
|
||||
// Memoizes the given closure, only calling the passed
|
||||
// closure once; even if repeat calls to the returned closure
|
||||
internal func memoizedClosure<T>(closure: () -> T) -> (Bool) -> T {
|
||||
var cache: T?
|
||||
return ({ withoutCaching in
|
||||
if (withoutCaching || cache == nil) {
|
||||
cache = closure()
|
||||
}
|
||||
return cache!
|
||||
})
|
||||
}
|
||||
|
||||
public struct Expression<T> {
|
||||
internal let _expression: (Bool) -> T?
|
||||
internal let _withoutCaching: Bool
|
||||
public let location: SourceLocation
|
||||
|
||||
public init(expression: () -> T?, location: SourceLocation) {
|
||||
self._expression = memoizedClosure(expression)
|
||||
self.location = location
|
||||
self._withoutCaching = false
|
||||
}
|
||||
|
||||
public init(memoizedExpression: (Bool) -> T?, location: SourceLocation, withoutCaching: Bool) {
|
||||
self._expression = memoizedExpression
|
||||
self.location = location
|
||||
self._withoutCaching = withoutCaching
|
||||
}
|
||||
|
||||
public func cast<U>(block: (T?) -> U?) -> Expression<U> {
|
||||
return Expression<U>(expression: ({ block(self.evaluate()) }), location: self.location)
|
||||
}
|
||||
|
||||
public func evaluate() -> T? {
|
||||
return self._expression(_withoutCaching)
|
||||
}
|
||||
|
||||
public func withoutCaching() -> Expression<T> {
|
||||
return Expression(memoizedExpression: self._expression, location: location, withoutCaching: true)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import Foundation
|
||||
|
||||
@objc
|
||||
public class FailureMessage {
|
||||
public var expected: String = "expected"
|
||||
public var actualValue: String? = "" // empty string -> use default; nil -> exclude
|
||||
public var to: String = "to"
|
||||
public var postfixMessage: String = "match"
|
||||
public var postfixActual: String = ""
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func stringValue() -> String {
|
||||
var value = "\(expected) \(to) \(postfixMessage)"
|
||||
if let actualValue = actualValue {
|
||||
value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)"
|
||||
}
|
||||
var lines: [String] = (value as NSString).componentsSeparatedByString("\n") as [String]
|
||||
let whitespace = NSCharacterSet.whitespaceAndNewlineCharacterSet()
|
||||
lines = lines.map { line in line.stringByTrimmingCharactersInSet(whitespace) }
|
||||
return "".join(lines)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is an instance of the given class.
|
||||
/// @see beAnInstanceOf if you want to match against the exact class
|
||||
public func beAKindOf(expectedClass: AnyClass) -> NonNilMatcherFunc<NSObject> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
let instance = actualExpression.evaluate()
|
||||
if let validInstance = instance {
|
||||
failureMessage.actualValue = "<\(NSStringFromClass(validInstance.dynamicType)) instance>"
|
||||
} else {
|
||||
failureMessage.actualValue = "<nil>"
|
||||
}
|
||||
failureMessage.postfixMessage = "be a kind of \(NSStringFromClass(expectedClass))"
|
||||
return instance != nil && instance!.isKindOfClass(expectedClass)
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beAKindOfMatcher(expected: AnyClass) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
return beAKindOf(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is an instance of the given class.
|
||||
/// @see beAKindOf if you want to match against subclasses
|
||||
public func beAnInstanceOf(expectedClass: AnyClass) -> NonNilMatcherFunc<NSObject> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
let instance = actualExpression.evaluate()
|
||||
if let validInstance = instance {
|
||||
failureMessage.actualValue = "<\(NSStringFromClass(validInstance.dynamicType)) instance>"
|
||||
} else {
|
||||
failureMessage.actualValue = "<nil>"
|
||||
}
|
||||
failureMessage.postfixMessage = "be an instance of \(NSStringFromClass(expectedClass))"
|
||||
return instance != nil && instance!.isMemberOfClass(expectedClass)
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beAnInstanceOfMatcher(expected: AnyClass) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
return beAnInstanceOf(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
import Foundation
|
||||
|
||||
let DefaultDelta = 0.0001
|
||||
|
||||
internal func isCloseTo(actualValue: Double?, expectedValue: Double, delta: Double, failureMessage: FailureMessage) -> Bool {
|
||||
failureMessage.postfixMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))"
|
||||
if actualValue != nil {
|
||||
failureMessage.actualValue = "<\(stringify(actualValue!))>"
|
||||
} else {
|
||||
failureMessage.actualValue = "<nil>"
|
||||
}
|
||||
return actualValue != nil && abs(actualValue! - expectedValue) < delta
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is close to another. This is used for floating
|
||||
/// point values which can have imprecise results when doing arithmetic on them.
|
||||
///
|
||||
/// @see equal
|
||||
public func beCloseTo(expectedValue: Double, within delta: Double = DefaultDelta) -> NonNilMatcherFunc<Double> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
return isCloseTo(actualExpression.evaluate(), expectedValue, delta, failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is close to another. This is used for floating
|
||||
/// point values which can have imprecise results when doing arithmetic on them.
|
||||
///
|
||||
/// @see equal
|
||||
public func beCloseTo(expectedValue: NMBDoubleConvertible, within delta: Double = DefaultDelta) -> NonNilMatcherFunc<NMBDoubleConvertible> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
return isCloseTo(actualExpression.evaluate()?.doubleValue, expectedValue.doubleValue, delta, failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class NMBObjCBeCloseToMatcher : NMBMatcher {
|
||||
var _expected: NSNumber
|
||||
var _delta: CDouble
|
||||
init(expected: NSNumber, within: CDouble) {
|
||||
_expected = expected
|
||||
_delta = within
|
||||
}
|
||||
|
||||
public func matches(actualExpression: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(beCloseTo(self._expected, within: self._delta)))
|
||||
return matcher.matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
|
||||
public func doesNotMatch(actualExpression: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let actualBlock: () -> NMBDoubleConvertible? = ({
|
||||
return actualExpression() as? NMBDoubleConvertible
|
||||
})
|
||||
let expr = Expression(expression: actualBlock, location: location)
|
||||
let matcher = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(beCloseTo(self._expected, within: self._delta)))
|
||||
return matcher.doesNotMatch(expr, failureMessage: failureMessage)
|
||||
}
|
||||
|
||||
public var within: (CDouble) -> NMBObjCBeCloseToMatcher {
|
||||
return ({ delta in
|
||||
return NMBObjCBeCloseToMatcher(expected: self._expected, within: delta)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beCloseToMatcher(expected: NSNumber, within: CDouble) -> NMBObjCBeCloseToMatcher {
|
||||
return NMBObjCBeCloseToMatcher(expected: expected, within: within)
|
||||
}
|
||||
}
|
||||
|
||||
public func beCloseTo(expectedValues: [Double], within delta: Double = DefaultDelta) -> NonNilMatcherFunc <[Double]> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))"
|
||||
if let actual = actualExpression.evaluate() {
|
||||
if actual.count != expectedValues.count {
|
||||
return false
|
||||
} else {
|
||||
for (index, actualItem) in enumerate(actual) {
|
||||
if fabs(actualItem - expectedValues[index]) > delta {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
infix operator ≈ {}
|
||||
|
||||
public func ≈(lhs: Expectation<[Double]>, rhs: [Double]) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
|
||||
public func ≈(lhs: Expectation<Double>, rhs: Double) {
|
||||
lhs.to(beCloseTo(rhs))
|
||||
}
|
||||
|
||||
public func ≈(lhs: Expectation<Double>, rhs: (expected: Double, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
|
||||
public func ==(lhs: Expectation<Double>, rhs: (expected: Double, delta: Double)) {
|
||||
lhs.to(beCloseTo(rhs.expected, within: rhs.delta))
|
||||
}
|
||||
|
||||
// make this higher precedence than exponents so the Doubles either end aren't pulled in
|
||||
// unexpectantly
|
||||
infix operator ± { precedence 170 }
|
||||
public func ±(lhs: Double, rhs: Double) -> (expected: Double, delta: Double) {
|
||||
return (expected: lhs, delta: rhs)
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty<S: SequenceType>() -> NonNilMatcherFunc<S> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
let actualSeq = actualExpression.evaluate()
|
||||
if actualSeq == nil {
|
||||
return true
|
||||
}
|
||||
var generator = actualSeq!.generate()
|
||||
return generator.next() == nil
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> NonNilMatcherFunc<NSString> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
let actualString = actualExpression.evaluate()
|
||||
return actualString == nil || actualString!.length == 0
|
||||
}
|
||||
}
|
||||
|
||||
// Without specific overrides, beEmpty() is ambiguous for NSDictionary, NSArray,
|
||||
// etc, since they conform to SequenceType as well as NMBCollection.
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> NonNilMatcherFunc<NSDictionary> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
let actualDictionary = actualExpression.evaluate()
|
||||
return actualDictionary == nil || actualDictionary!.count == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> NonNilMatcherFunc<NSArray> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
let actualArray = actualExpression.evaluate()
|
||||
return actualArray == nil || actualArray!.count == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when a value is "empty". For collections, this
|
||||
/// means the are no items in that collection. For strings, it is an empty string.
|
||||
public func beEmpty() -> NonNilMatcherFunc<NMBCollection> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
let actual = actualExpression.evaluate()
|
||||
return actual == nil || actual!.count == 0
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beEmptyMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let actualValue = actualExpression.evaluate()
|
||||
failureMessage.postfixMessage = "be empty"
|
||||
if let value = actualValue as? NMBCollection {
|
||||
let expr = Expression(expression: ({ value as NMBCollection }), location: location)
|
||||
return beEmpty().matches(expr, failureMessage: failureMessage)
|
||||
} else if let value = actualValue as? NSString {
|
||||
let expr = Expression(expression: ({ value as String }), location: location)
|
||||
return beEmpty().matches(expr, failureMessage: failureMessage)
|
||||
} else if let actualValue = actualValue {
|
||||
failureMessage.postfixMessage = "be empty (only works for NSArrays, NSSets, NSDictionaries, NSHashTables, and NSStrings)"
|
||||
failureMessage.actualValue = "\(NSStringFromClass(actualValue.dynamicType)) type"
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than the expected value.
|
||||
public func beGreaterThan<T: Comparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
return actualExpression.evaluate() > expectedValue
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than the expected value.
|
||||
public func beGreaterThan(expectedValue: NMBComparable?) -> NonNilMatcherFunc<NMBComparable> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == NSComparisonResult.OrderedDescending
|
||||
return matches
|
||||
}
|
||||
}
|
||||
|
||||
public func ><T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
public func >(lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beGreaterThan(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beGreaterThanMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { $0 as NMBComparable? }
|
||||
return beGreaterThan(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: Comparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
return actualValue >= expectedValue
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is greater than
|
||||
/// or equal to the expected value.
|
||||
public func beGreaterThanOrEqualTo<T: NMBComparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be greater than or equal to <\(stringify(expectedValue))>"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != NSComparisonResult.OrderedAscending
|
||||
return matches
|
||||
}
|
||||
}
|
||||
|
||||
public func >=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
public func >=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beGreaterThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beGreaterThanOrEqualToMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { $0 as NMBComparable? }
|
||||
return beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is the same instance
|
||||
/// as the expected instance.
|
||||
public func beIdenticalTo<T: AnyObject>(expected: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
let actual = actualExpression.evaluate()
|
||||
failureMessage.actualValue = "\(identityAsString(actual))"
|
||||
failureMessage.postfixMessage = "be identical to \(identityAsString(expected))"
|
||||
return actual === expected && actual !== nil
|
||||
}
|
||||
}
|
||||
|
||||
public func ===<T: AnyObject>(lhs: Expectation<T>, rhs: T?) {
|
||||
lhs.to(beIdenticalTo(rhs))
|
||||
}
|
||||
public func !==<T: AnyObject>(lhs: Expectation<T>, rhs: T?) {
|
||||
lhs.toNot(beIdenticalTo(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beIdenticalToMatcher(expected: NSObject?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
return beIdenticalTo(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan<T: Comparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>"
|
||||
return actualExpression.evaluate() < expectedValue
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than the expected value.
|
||||
public func beLessThan(expectedValue: NMBComparable?) -> NonNilMatcherFunc<NMBComparable> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == NSComparisonResult.OrderedAscending
|
||||
return matches
|
||||
}
|
||||
}
|
||||
|
||||
public func <<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
public func <(lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
|
||||
lhs.to(beLessThan(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beLessThanMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { $0 as NMBComparable? }
|
||||
return beLessThan(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: Comparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>"
|
||||
return actualExpression.evaluate() <= expectedValue
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is less than
|
||||
/// or equal to the expected value.
|
||||
public func beLessThanOrEqualTo<T: NMBComparable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be less than or equal to <\(stringify(expectedValue))>"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
return actualValue != nil && actualValue!.NMB_compare(expectedValue) != NSComparisonResult.OrderedDescending
|
||||
}
|
||||
}
|
||||
|
||||
public func <=<T: Comparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
public func <=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
|
||||
lhs.to(beLessThanOrEqualTo(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beLessThanOrEqualToMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil:false) { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { $0 as? NMBComparable }
|
||||
return beLessThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import Foundation
|
||||
|
||||
internal func beBool(#expectedValue: BooleanType, #stringValue: String, #falseMatchesNil: Bool) -> MatcherFunc<BooleanType> {
|
||||
return MatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be \(stringValue)"
|
||||
let actual = actualExpression.evaluate()
|
||||
if expectedValue {
|
||||
return actual?.boolValue == expectedValue.boolValue
|
||||
} else if !falseMatchesNil {
|
||||
return actual != nil && actual!.boolValue != !expectedValue.boolValue
|
||||
} else {
|
||||
return actual?.boolValue != !expectedValue.boolValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: beTrue() / beFalse()
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is exactly true.
|
||||
/// This matcher will not match against nils.
|
||||
public func beTrue() -> NonNilMatcherFunc<Bool> {
|
||||
return basicMatcherWithFailureMessage(equal(true)) { failureMessage in
|
||||
failureMessage.postfixMessage = "be true"
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is exactly false.
|
||||
/// This matcher will not match against nils.
|
||||
public func beFalse() -> NonNilMatcherFunc<Bool> {
|
||||
return basicMatcherWithFailureMessage(equal(false)) { failureMessage in
|
||||
failureMessage.postfixMessage = "be false"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: beTruthy() / beFalsy()
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is not logically false.
|
||||
public func beTruthy() -> MatcherFunc<BooleanType> {
|
||||
return beBool(expectedValue: true, stringValue: "truthy", falseMatchesNil: true)
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is logically false.
|
||||
/// This matcher will match against nils.
|
||||
public func beFalsy() -> MatcherFunc<BooleanType> {
|
||||
return beBool(expectedValue: false, stringValue: "falsy", falseMatchesNil: true)
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beTruthyMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false as BooleanType? }
|
||||
return beTruthy().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public class func beFalsyMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false as BooleanType? }
|
||||
return beFalsy().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public class func beTrueMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false as Bool? }
|
||||
return beTrue().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public class func beFalseMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let expr = actualExpression.cast { ($0 as? NSNumber)?.boolValue ?? false as Bool? }
|
||||
return beFalse().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is nil.
|
||||
public func beNil<T>() -> MatcherFunc<T> {
|
||||
return MatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "be nil"
|
||||
let actualValue = actualExpression.evaluate()
|
||||
return actualValue == nil
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beNilMatcher() -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher { actualExpression, failureMessage, location in
|
||||
return beNil().matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence's first element
|
||||
/// is equal to the expected value.
|
||||
public func beginWith<S: SequenceType, T: Equatable where S.Generator.Element == T>(startingElement: T) -> NonNilMatcherFunc<S> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingElement)>"
|
||||
if let actualValue = actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.generate()
|
||||
return actualGenerator.next() == startingElement
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection's first element
|
||||
/// is equal to the expected object.
|
||||
public func beginWith(startingElement: AnyObject) -> NonNilMatcherFunc<NMBOrderedCollection> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingElement)>"
|
||||
let collection = actualExpression.evaluate()
|
||||
return collection != nil && collection!.indexOfObject(startingElement) == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains expected substring
|
||||
/// where the expected substring's location is zero.
|
||||
public func beginWith(startingSubstring: String) -> NonNilMatcherFunc<String> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "begin with <\(startingSubstring)>"
|
||||
if let actual = actualExpression.evaluate() {
|
||||
let range = actual.rangeOfString(startingSubstring)
|
||||
return range != nil && range!.startIndex == actual.startIndex
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func beginWithMatcher(expected: AnyObject) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let actual = actualExpression.evaluate()
|
||||
if let actualString = actual as? String {
|
||||
let expr = actualExpression.cast { $0 as? String }
|
||||
return beginWith(expected as String).matches(expr, failureMessage: failureMessage)
|
||||
} else {
|
||||
let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
|
||||
return beginWith(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence contains the expected value.
|
||||
public func contain<S: SequenceType, T: Equatable where S.Generator.Element == T>(items: T...) -> NonNilMatcherFunc<S> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(items))>"
|
||||
if let actual = actualExpression.evaluate() {
|
||||
return all(items) {
|
||||
return contains(actual, $0)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
|
||||
public func contain(substrings: String...) -> NonNilMatcherFunc<String> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>"
|
||||
if let actual = actualExpression.evaluate() {
|
||||
return all(substrings) {
|
||||
let scanRange = Range(start: actual.startIndex, end: actual.endIndex)
|
||||
let range = actual.rangeOfString($0, options: nil, range: scanRange, locale: nil)
|
||||
return range != nil && !range!.isEmpty
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection contains the expected object.
|
||||
public func contain(items: AnyObject?...) -> NonNilMatcherFunc<NMBContainer> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "contain <\(arrayAsString(items))>"
|
||||
let actual = actualExpression.evaluate()
|
||||
return all(items) { item in
|
||||
return actual != nil && actual!.containsObject(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func containMatcher(expected: NSObject?) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let actualValue = actualExpression.evaluate()
|
||||
if let value = actualValue as? NMBContainer {
|
||||
let expr = Expression(expression: ({ value as NMBContainer }), location: location)
|
||||
return contain(expected).matches(expr, failureMessage: failureMessage)
|
||||
} else if let value = actualValue as? NSString {
|
||||
let expr = Expression(expression: ({ value as String }), location: location)
|
||||
return contain(expected as String).matches(expr, failureMessage: failureMessage)
|
||||
} else if actualValue != nil {
|
||||
failureMessage.postfixMessage = "contain <\(stringify(expected))> (only works for NSArrays, NSSets, NSHashTables, and NSStrings)"
|
||||
} else {
|
||||
failureMessage.postfixMessage = "contain <\(stringify(expected))>"
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual sequence's last element
|
||||
/// is equal to the expected value.
|
||||
public func endWith<S: SequenceType, T: Equatable where S.Generator.Element == T>(endingElement: T) -> NonNilMatcherFunc<S> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingElement)>"
|
||||
|
||||
if let actualValue = actualExpression.evaluate() {
|
||||
var actualGenerator = actualValue.generate()
|
||||
var lastItem: T?
|
||||
var item: T?
|
||||
do {
|
||||
lastItem = item
|
||||
item = actualGenerator.next()
|
||||
} while(item != nil)
|
||||
|
||||
return lastItem == endingElement
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection's last element
|
||||
/// is equal to the expected object.
|
||||
public func endWith(endingElement: AnyObject) -> NonNilMatcherFunc<NMBOrderedCollection> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingElement)>"
|
||||
let collection = actualExpression.evaluate()
|
||||
return collection != nil && collection!.indexOfObject(endingElement) == collection!.count - 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string contains the expected substring
|
||||
/// where the expected substring's location is the actual string's length minus the
|
||||
/// expected substring's length.
|
||||
public func endWith(endingSubstring: String) -> NonNilMatcherFunc<String> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "end with <\(endingSubstring)>"
|
||||
if let collection = actualExpression.evaluate() {
|
||||
let range = collection.rangeOfString(endingSubstring)
|
||||
return range != nil && range!.endIndex == collection.endIndex
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func endWithMatcher(expected: AnyObject) -> NMBObjCMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let actual = actualExpression.evaluate()
|
||||
if let actualString = actual as? String {
|
||||
let expr = Expression(expression: ({ actualString }), location: location)
|
||||
return endWith(expected as String).matches(expr, failureMessage: failureMessage)
|
||||
} else {
|
||||
let expr = Expression(expression: ({ actual as? NMBOrderedCollection }), location: location)
|
||||
return endWith(expected).matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
|
||||
/// Values can support equal by supporting the Equatable protocol.
|
||||
///
|
||||
/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles).
|
||||
public func equal<T: Equatable>(expectedValue: T?) -> NonNilMatcherFunc<T> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>"
|
||||
let matches = actualExpression.evaluate() == expectedValue && expectedValue != nil
|
||||
if expectedValue == nil || actualExpression.evaluate() == nil {
|
||||
if expectedValue == nil {
|
||||
failureMessage.postfixActual = " (use beNil() to match nils)"
|
||||
}
|
||||
return false
|
||||
}
|
||||
return matches
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual value is equal to the expected value.
|
||||
/// Values can support equal by supporting the Equatable protocol.
|
||||
///
|
||||
/// @see beCloseTo if you want to match imprecise types (eg - floats, doubles).
|
||||
public func equal<T: Equatable, C: Equatable>(expectedValue: [T: C]?) -> NonNilMatcherFunc<[T: C]> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>"
|
||||
if expectedValue == nil || actualExpression.evaluate() == nil {
|
||||
if expectedValue == nil {
|
||||
failureMessage.postfixActual = " (use beNil() to match nils)"
|
||||
}
|
||||
return false
|
||||
}
|
||||
return expectedValue! == actualExpression.evaluate()!
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual collection is equal to the expected collection.
|
||||
/// Items must implement the Equatable protocol.
|
||||
public func equal<T: Equatable>(expectedValue: [T]?) -> NonNilMatcherFunc<[T]> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>"
|
||||
if expectedValue == nil || actualExpression.evaluate() == nil {
|
||||
if expectedValue == nil {
|
||||
failureMessage.postfixActual = " (use beNil() to match nils)"
|
||||
}
|
||||
return false
|
||||
}
|
||||
return expectedValue! == actualExpression.evaluate()!
|
||||
}
|
||||
}
|
||||
|
||||
public func ==<T: Equatable>(lhs: Expectation<T>, rhs: T?) {
|
||||
lhs.to(equal(rhs))
|
||||
}
|
||||
|
||||
public func !=<T: Equatable>(lhs: Expectation<T>, rhs: T?) {
|
||||
lhs.toNot(equal(rhs))
|
||||
}
|
||||
|
||||
public func ==<T: Equatable>(lhs: Expectation<[T]>, rhs: [T]?) {
|
||||
lhs.to(equal(rhs))
|
||||
}
|
||||
|
||||
public func !=<T: Equatable>(lhs: Expectation<[T]>, rhs: [T]?) {
|
||||
lhs.toNot(equal(rhs))
|
||||
}
|
||||
|
||||
public func ==<T: Equatable, C: Equatable>(lhs: Expectation<[T: C]>, rhs: [T: C]?) {
|
||||
lhs.to(equal(rhs))
|
||||
}
|
||||
|
||||
public func !=<T: Equatable, C: Equatable>(lhs: Expectation<[T: C]>, rhs: [T: C]?) {
|
||||
lhs.toNot(equal(rhs))
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func equalMatcher(expected: NSObject) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
return equal(expected).matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import Foundation
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual string satisfies the regular expression
|
||||
/// described by the expected string.
|
||||
public func match(expectedValue: String?) -> NonNilMatcherFunc<String> {
|
||||
return NonNilMatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.postfixMessage = "match <\(stringify(expectedValue))>"
|
||||
|
||||
if let actual = actualExpression.evaluate() {
|
||||
if let regexp = expectedValue {
|
||||
return actual.rangeOfString(regexp, options: .RegularExpressionSearch) != nil
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func matchMatcher(expected: NSString) -> NMBMatcher {
|
||||
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
|
||||
let actual = actualExpression.cast { $0 as? String }
|
||||
return match(expected).matches(actual, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
/// Implement this protocol if you want full control over to() and toNot() behaviors
|
||||
/// when matching a value.
|
||||
public protocol Matcher {
|
||||
typealias ValueType
|
||||
func matches(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
|
||||
func doesNotMatch(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
|
||||
}
|
||||
|
||||
/// Implement this protocol if you just want a simplier matcher. The negation
|
||||
/// is provided for you automatically.
|
||||
///
|
||||
/// If you just want a very simplified usage of BasicMatcher,
|
||||
/// @see MatcherFunc.
|
||||
public protocol BasicMatcher {
|
||||
typealias ValueType
|
||||
func matches(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
|
||||
}
|
||||
|
||||
|
||||
/// Implement this protocol if you want a matcher only work for non-nil values.
|
||||
/// The matcher still needs to properly handle nil values, but using this type will
|
||||
/// tell Nimble to automatically postfix a nil match error (and automatically fail the match).
|
||||
///
|
||||
/// Unlike a naive implementation of the matches interface, NonNilBasicMatcher will also
|
||||
/// fail for the negation to a nil:
|
||||
///
|
||||
/// // objc
|
||||
/// expect(nil).to(matchWithMyCustomNonNilBasicMatcher()) // => fails
|
||||
/// expect(nil).toNot(matchWithMyCustomNonNilBasicMatcher()) // => fails
|
||||
///
|
||||
/// @see BasicMatcher
|
||||
public protocol NonNilBasicMatcher {
|
||||
typealias ValueType
|
||||
func matches(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
|
||||
}
|
||||
|
||||
/// Objective-C interface to the Swift variant of Matcher. This gives you full control over
|
||||
/// to() and toNot() behaviors when matching a value.
|
||||
@objc public protocol NMBMatcher {
|
||||
func matches(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
func doesNotMatch(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
}
|
||||
|
||||
/// Protocol for types that support contain() matcher.
|
||||
@objc public protocol NMBContainer {
|
||||
func containsObject(object: AnyObject!) -> Bool
|
||||
}
|
||||
extension NSArray : NMBContainer {}
|
||||
extension NSSet : NMBContainer {}
|
||||
extension NSHashTable : NMBContainer {}
|
||||
|
||||
/// Protocol for types that support only beEmpty()
|
||||
@objc public protocol NMBCollection {
|
||||
var count: Int { get }
|
||||
}
|
||||
extension NSSet : NMBCollection {}
|
||||
extension NSDictionary : NMBCollection {}
|
||||
extension NSHashTable : NMBCollection {}
|
||||
|
||||
/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers
|
||||
@objc public protocol NMBOrderedCollection : NMBCollection {
|
||||
func indexOfObject(object: AnyObject!) -> Int
|
||||
}
|
||||
extension NSArray : NMBOrderedCollection {}
|
||||
|
||||
/// Protocol for types to support beCloseTo() matcher
|
||||
@objc public protocol NMBDoubleConvertible {
|
||||
var doubleValue: CDouble { get }
|
||||
}
|
||||
extension NSNumber : NMBDoubleConvertible { }
|
||||
extension NSDecimalNumber : NMBDoubleConvertible { } // TODO: not the best to downsize
|
||||
|
||||
/// Protocol for types to support beLessThan(), beLessThanOrEqualTo(),
|
||||
/// beGreaterThan(), beGreaterThanOrEqualTo(), and equal() matchers.
|
||||
///
|
||||
/// Types that conform to Swift's Comparable protocol will work implicitly too
|
||||
@objc public protocol NMBComparable {
|
||||
func NMB_compare(otherObject: NMBComparable!) -> NSComparisonResult
|
||||
}
|
||||
extension NSNumber : NMBComparable {
|
||||
public func NMB_compare(otherObject: NMBComparable!) -> NSComparisonResult {
|
||||
return compare(otherObject as NSNumber)
|
||||
}
|
||||
}
|
||||
extension NSString : NMBComparable {
|
||||
public func NMB_compare(otherObject: NMBComparable!) -> NSComparisonResult {
|
||||
return compare(otherObject as NSString)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
import Foundation
|
||||
|
||||
internal func raiseExceptionMatcher<T>(message: String, matches: (NSException?) -> Bool) -> MatcherFunc<T> {
|
||||
return MatcherFunc { actualExpression, failureMessage in
|
||||
failureMessage.actualValue = nil
|
||||
failureMessage.postfixMessage = message
|
||||
|
||||
// It would be better if this was part of Expression, but
|
||||
// Swift compiler crashes when expect() is inside a closure.
|
||||
var exception: NSException?
|
||||
var result: T?
|
||||
var capture = NMBExceptionCapture(handler: ({ e in
|
||||
exception = e
|
||||
}), finally: nil)
|
||||
|
||||
capture.tryBlock {
|
||||
actualExpression.evaluate()
|
||||
return
|
||||
}
|
||||
return matches(exception)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an exception with
|
||||
/// the specified name, reason, and userInfo.
|
||||
public func raiseException(#named: String, #reason: String, #userInfo: NSDictionary) -> MatcherFunc<Any> {
|
||||
return raiseExceptionMatcher("raise exception named <\(named)> with reason <\(reason)> and userInfo <\(userInfo)>") {
|
||||
exception in
|
||||
return exception?.name == named
|
||||
&& exception?.reason == reason
|
||||
&& exception?.userInfo == userInfo
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an exception with
|
||||
/// the specified name and reason.
|
||||
public func raiseException(#named: String, #reason: String) -> MatcherFunc<Any> {
|
||||
return raiseExceptionMatcher("raise exception named <\(named)> with reason <\(reason)>") {
|
||||
exception in return exception?.name == named && exception?.reason == reason
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises an exception with
|
||||
/// the specified name.
|
||||
public func raiseException(#named: String) -> MatcherFunc<Any> {
|
||||
return raiseExceptionMatcher("raise exception named <\(named)>") {
|
||||
exception in return exception?.name == named
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nimble matcher that succeeds when the actual expression raises any exception.
|
||||
/// Please use a more specific raiseException() matcher when possible.
|
||||
public func raiseException() -> MatcherFunc<Any> {
|
||||
return raiseExceptionMatcher("raise any exception") {
|
||||
exception in return exception != nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc public class NMBObjCRaiseExceptionMatcher : NMBMatcher {
|
||||
var _name: String?
|
||||
var _reason: String?
|
||||
var _userInfo: NSDictionary?
|
||||
init(name: String?, reason: String?, userInfo: NSDictionary?) {
|
||||
_name = name
|
||||
_reason = reason
|
||||
_userInfo = userInfo
|
||||
}
|
||||
|
||||
public func matches(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let block: () -> Any? = ({ actualBlock(); return nil })
|
||||
let expr = Expression(expression: block, location: location)
|
||||
if _name != nil && _reason != nil && _userInfo != nil {
|
||||
return raiseException(named: _name!, reason: _reason!, userInfo: _userInfo!).matches(expr, failureMessage: failureMessage)
|
||||
} else if _name != nil && _reason != nil {
|
||||
return raiseException(named: _name!, reason: _reason!).matches(expr, failureMessage: failureMessage)
|
||||
} else if _name != nil {
|
||||
return raiseException(named: _name!).matches(expr, failureMessage: failureMessage)
|
||||
} else {
|
||||
return raiseException().matches(expr, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public func doesNotMatch(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
return !matches(actualBlock, failureMessage: failureMessage, location: location)
|
||||
}
|
||||
|
||||
public var named: (name: String) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ name in
|
||||
return NMBObjCRaiseExceptionMatcher(name: name, reason: self._reason, userInfo: self._userInfo)
|
||||
})
|
||||
}
|
||||
|
||||
public var reason: (reason: String?) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ reason in
|
||||
return NMBObjCRaiseExceptionMatcher(name: self._name, reason: reason, userInfo: self._userInfo)
|
||||
})
|
||||
}
|
||||
|
||||
public var userInfo: (userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher {
|
||||
return ({ userInfo in
|
||||
return NMBObjCRaiseExceptionMatcher(name: self._name, reason: self._reason, userInfo: userInfo)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
extension NMBObjCMatcher {
|
||||
public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher {
|
||||
return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <Nimble/NMBExceptionCapture.h>
|
||||
#import <Nimble/DSL.h>
|
||||
|
||||
FOUNDATION_EXPORT double NimbleVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char NimbleVersionString[];
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import Foundation
|
||||
|
||||
internal func all<T>(array: [T], fn: (T) -> Bool) -> Bool {
|
||||
for item in array {
|
||||
if !fn(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import Foundation
|
||||
|
||||
internal enum PollResult : BooleanType {
|
||||
case Success, Failure, Timeout
|
||||
|
||||
var boolValue : Bool {
|
||||
return self == .Success
|
||||
}
|
||||
}
|
||||
|
||||
internal class RunPromise {
|
||||
var token: dispatch_once_t = 0
|
||||
var didFinish = false
|
||||
var didFail = false
|
||||
|
||||
init() {}
|
||||
|
||||
func succeed() {
|
||||
dispatch_once(&self.token) {
|
||||
self.didFinish = false
|
||||
}
|
||||
}
|
||||
|
||||
func fail(block: () -> Void) {
|
||||
dispatch_once(&self.token) {
|
||||
self.didFail = true
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal func stopRunLoop(runLoop: NSRunLoop, delay: NSTimeInterval) -> RunPromise {
|
||||
var promise = RunPromise()
|
||||
var killQueue = dispatch_queue_create("nimble.waitUntil.queue", DISPATCH_QUEUE_SERIAL)
|
||||
let killTimeOffset = Int64(CDouble(delay) * CDouble(NSEC_PER_SEC))
|
||||
let killTime = dispatch_time(DISPATCH_TIME_NOW, killTimeOffset)
|
||||
dispatch_after(killTime, killQueue) {
|
||||
promise.fail {
|
||||
CFRunLoopStop(runLoop.getCFRunLoop())
|
||||
}
|
||||
}
|
||||
return promise
|
||||
}
|
||||
|
||||
internal func pollBlock(#pollInterval: NSTimeInterval, #timeoutInterval: NSTimeInterval, expression: () -> Bool) -> PollResult {
|
||||
let runLoop = NSRunLoop.mainRunLoop()
|
||||
|
||||
var promise = stopRunLoop(runLoop, min(timeoutInterval, 0.2))
|
||||
|
||||
let startDate = NSDate()
|
||||
|
||||
// trigger run loop to make sure enqueued tasks don't block our assertion polling
|
||||
// the stop run loop task above will abort us if necessary
|
||||
runLoop.runUntilDate(startDate)
|
||||
promise.succeed()
|
||||
|
||||
if promise.didFail {
|
||||
return .Timeout
|
||||
}
|
||||
|
||||
var pass: Bool = false
|
||||
do {
|
||||
pass = expression()
|
||||
if pass {
|
||||
break
|
||||
}
|
||||
|
||||
let runDate = NSDate().dateByAddingTimeInterval(pollInterval) as NSDate
|
||||
runLoop.runUntilDate(runDate)
|
||||
} while(NSDate().timeIntervalSinceDate(startDate) < timeoutInterval);
|
||||
|
||||
return pass ? .Success : .Failure
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
@objc public class SourceLocation : Printable {
|
||||
public let file: String
|
||||
public let line: UInt
|
||||
|
||||
init() {
|
||||
file = "Unknown File"
|
||||
line = 0
|
||||
}
|
||||
|
||||
init(file: String, line: UInt) {
|
||||
self.file = file
|
||||
self.line = line
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
return "\(file):\(line)"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
internal func identityAsString(value: AnyObject?) -> String {
|
||||
if value == nil {
|
||||
return "nil"
|
||||
}
|
||||
return NSString(format: "<%p>", unsafeBitCast(value!, Int.self))
|
||||
}
|
||||
|
||||
internal func arrayAsString<T>(items: [T], joiner: String = ", ") -> String {
|
||||
return items.reduce("") { accum, item in
|
||||
let prefix = (accum.isEmpty ? "" : joiner)
|
||||
return accum + prefix + "\(stringify(item))"
|
||||
}
|
||||
}
|
||||
|
||||
@objc protocol NMBStringer {
|
||||
func NMB_stringify() -> String
|
||||
}
|
||||
|
||||
internal func stringify<S: SequenceType>(value: S) -> String {
|
||||
var generator = value.generate()
|
||||
var strings = [String]()
|
||||
var value: S.Generator.Element?
|
||||
do {
|
||||
value = generator.next()
|
||||
if value != nil {
|
||||
strings.append(stringify(value))
|
||||
}
|
||||
} while value != nil
|
||||
let str = ", ".join(strings)
|
||||
return "[\(str)]"
|
||||
}
|
||||
|
||||
extension NSArray : NMBStringer {
|
||||
func NMB_stringify() -> String {
|
||||
let str = self.componentsJoinedByString(", ")
|
||||
return "[\(str)]"
|
||||
}
|
||||
}
|
||||
|
||||
internal func stringify<T>(value: T) -> String {
|
||||
if value is Double {
|
||||
return NSString(format: "%.4f", (value as Double))
|
||||
}
|
||||
return toString(value)
|
||||
}
|
||||
|
||||
internal func stringify<T>(value: T?) -> String {
|
||||
if let unboxed = value {
|
||||
return stringify(unboxed)
|
||||
}
|
||||
return "nil"
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import Foundation
|
||||
|
||||
struct AsyncMatcherWrapper<T, U where U: Matcher, U.ValueType == T>: Matcher {
|
||||
let fullMatcher: U
|
||||
let timeoutInterval: NSTimeInterval = 1
|
||||
let pollInterval: NSTimeInterval = 0.01
|
||||
|
||||
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let uncachedExpression = actualExpression.withoutCaching()
|
||||
let result = pollBlock(pollInterval: pollInterval, timeoutInterval: timeoutInterval) {
|
||||
self.fullMatcher.matches(uncachedExpression, failureMessage: failureMessage)
|
||||
}
|
||||
switch (result) {
|
||||
case .Success: return true
|
||||
case .Failure: return false
|
||||
case .Timeout:
|
||||
failureMessage.postfixMessage += " (Stall on main thread)."
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let uncachedExpression = actualExpression.withoutCaching()
|
||||
let result = pollBlock(pollInterval: pollInterval, timeoutInterval: timeoutInterval) {
|
||||
self.fullMatcher.doesNotMatch(uncachedExpression, failureMessage: failureMessage)
|
||||
}
|
||||
switch (result) {
|
||||
case .Success: return true
|
||||
case .Failure: return false
|
||||
case .Timeout:
|
||||
failureMessage.postfixMessage += " (Stall on main thread)."
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Expectation {
|
||||
public func toEventually<U where U: Matcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {
|
||||
to(AsyncMatcherWrapper(
|
||||
fullMatcher: FullMatcherWrapper(
|
||||
matcher: matcher,
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeoutInterval: timeout,
|
||||
pollInterval: pollInterval))
|
||||
}
|
||||
|
||||
public func toEventuallyNot<U where U: Matcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {
|
||||
toNot(AsyncMatcherWrapper(
|
||||
fullMatcher: FullMatcherWrapper(
|
||||
matcher: matcher,
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeoutInterval: timeout,
|
||||
pollInterval: pollInterval))
|
||||
}
|
||||
|
||||
public func toEventually<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {
|
||||
toEventually(
|
||||
FullMatcherWrapper(
|
||||
matcher: BasicMatcherWrapper(matcher: matcher),
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeout: timeout,
|
||||
pollInterval: pollInterval)
|
||||
}
|
||||
|
||||
public func toEventuallyNot<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {
|
||||
toEventuallyNot(
|
||||
FullMatcherWrapper(
|
||||
matcher: BasicMatcherWrapper(matcher: matcher),
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeout: timeout,
|
||||
pollInterval: pollInterval)
|
||||
}
|
||||
|
||||
public func toEventually<U where U: NonNilBasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
|
||||
toEventually(
|
||||
FullMatcherWrapper(
|
||||
matcher: NonNilMatcherWrapper(NonNilBasicMatcherWrapper(matcher)),
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeout: timeout,
|
||||
pollInterval: pollInterval)
|
||||
}
|
||||
|
||||
public func toEventuallyNot<U where U: NonNilBasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
|
||||
toEventuallyNot(
|
||||
FullMatcherWrapper(
|
||||
matcher: NonNilMatcherWrapper(NonNilBasicMatcherWrapper(matcher)),
|
||||
to: "to eventually",
|
||||
toNot: "to eventually not"),
|
||||
timeout: timeout,
|
||||
pollInterval: pollInterval)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
struct BasicMatcherWrapper<M, T where M: BasicMatcher, M.ValueType == T>: Matcher {
|
||||
let matcher: M
|
||||
|
||||
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return !matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
extension Expectation {
|
||||
public func to<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
to(FullMatcherWrapper(matcher: BasicMatcherWrapper(matcher: matcher), to: "to", toNot: "to not"))
|
||||
}
|
||||
|
||||
public func toNot<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
toNot(FullMatcherWrapper(matcher: BasicMatcherWrapper(matcher: matcher), to: "to", toNot: "to not"))
|
||||
}
|
||||
|
||||
public func notTo<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
toNot(matcher)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import Foundation
|
||||
|
||||
|
||||
struct FullMatcherWrapper<M, T where M: Matcher, M.ValueType == T>: Matcher {
|
||||
let matcher: M
|
||||
let to: String
|
||||
let toNot: String
|
||||
|
||||
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
failureMessage.to = to
|
||||
return matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
failureMessage.to = toNot
|
||||
return matcher.doesNotMatch(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
|
||||
public struct FullMatcherFunc<T>: Matcher {
|
||||
public let matcher: (Expression<T>, FailureMessage, Bool) -> Bool
|
||||
|
||||
public init(_ matcher: (Expression<T>, FailureMessage, Bool) -> Bool) {
|
||||
self.matcher = matcher
|
||||
}
|
||||
|
||||
public func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher(actualExpression, failureMessage, false)
|
||||
}
|
||||
|
||||
public func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return !matcher(actualExpression, failureMessage, true)
|
||||
}
|
||||
}
|
||||
|
||||
public struct MatcherFunc<T>: BasicMatcher {
|
||||
public let matcher: (Expression<T>, FailureMessage) -> Bool
|
||||
|
||||
public init(_ matcher: (Expression<T>, FailureMessage) -> Bool) {
|
||||
self.matcher = matcher
|
||||
}
|
||||
|
||||
public func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher(actualExpression, failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public struct NonNilMatcherFunc<T>: NonNilBasicMatcher {
|
||||
public let matcher: (Expression<T>, FailureMessage) -> Bool
|
||||
|
||||
public init(_ matcher: (Expression<T>, FailureMessage) -> Bool) {
|
||||
self.matcher = matcher
|
||||
}
|
||||
|
||||
public func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher(actualExpression, failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
public func fullMatcherFromBasicMatcher<M: BasicMatcher>(matcher: M) -> FullMatcherFunc<M.ValueType> {
|
||||
return FullMatcherFunc { actualExpression, failureMessage, expectingToNotMatch in
|
||||
return matcher.matches(actualExpression, failureMessage: failureMessage) != expectingToNotMatch
|
||||
}
|
||||
}
|
||||
|
||||
public func basicMatcherWithFailureMessage<M: NonNilBasicMatcher>(matcher: M, postprocessor: (FailureMessage) -> Void) -> NonNilMatcherFunc<M.ValueType> {
|
||||
return NonNilMatcherFunc<M.ValueType> { actualExpression, failureMessage in
|
||||
let result = matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
postprocessor(failureMessage)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
struct NonNilMatcherWrapper<M: Matcher, T where M.ValueType == T>: Matcher {
|
||||
let matcher: M
|
||||
let nilMessage = " (use beNil() to match nils)"
|
||||
|
||||
init(_ matcher: M) {
|
||||
self.matcher = matcher
|
||||
}
|
||||
|
||||
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let pass = matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
if actualExpression.evaluate() == nil {
|
||||
failureMessage.postfixActual = nilMessage
|
||||
return false
|
||||
}
|
||||
return pass
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
let pass = matcher.doesNotMatch(actualExpression, failureMessage: failureMessage)
|
||||
if actualExpression.evaluate() == nil {
|
||||
failureMessage.postfixActual = nilMessage
|
||||
return false
|
||||
}
|
||||
return pass
|
||||
}
|
||||
}
|
||||
|
||||
struct NonNilBasicMatcherWrapper<M, T where M: NonNilBasicMatcher, M.ValueType == T>: Matcher {
|
||||
let matcher: M
|
||||
|
||||
init(_ matcher: M) {
|
||||
self.matcher = matcher
|
||||
}
|
||||
|
||||
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
|
||||
return !matcher.matches(actualExpression, failureMessage: failureMessage)
|
||||
}
|
||||
}
|
||||
|
||||
extension Expectation {
|
||||
public func to<U where U: NonNilBasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
to(FullMatcherWrapper(matcher: NonNilMatcherWrapper(NonNilBasicMatcherWrapper(matcher)), to: "to", toNot: "to not"))
|
||||
}
|
||||
|
||||
public func toNot<U where U: NonNilBasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
toNot(FullMatcherWrapper(matcher: NonNilMatcherWrapper(NonNilBasicMatcherWrapper(matcher)), to: "to", toNot: "to not"))
|
||||
}
|
||||
|
||||
public func notTo<U where U: NonNilBasicMatcher, U.ValueType == T>(matcher: U) {
|
||||
toNot(matcher)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
import Foundation
|
||||
|
||||
struct ObjCMatcherWrapper : Matcher {
|
||||
let matcher: NMBMatcher
|
||||
let to: String
|
||||
let toNot: String
|
||||
|
||||
func matches(actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
failureMessage.to = to
|
||||
return matcher.matches(({ actualExpression.evaluate() }), failureMessage: failureMessage, location: actualExpression.location)
|
||||
}
|
||||
|
||||
func doesNotMatch(actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
failureMessage.to = toNot
|
||||
return matcher.doesNotMatch(({ actualExpression.evaluate() }), failureMessage: failureMessage, location: actualExpression.location)
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent to Expectation, but simplified for ObjC objects only
|
||||
public class NMBExpectation : NSObject {
|
||||
let _actualBlock: () -> NSObject!
|
||||
var _negative: Bool
|
||||
let _file: String
|
||||
let _line: UInt
|
||||
var _timeout: NSTimeInterval = 1.0
|
||||
|
||||
public init(actualBlock: () -> NSObject!, negative: Bool, file: String, line: UInt) {
|
||||
self._actualBlock = actualBlock
|
||||
self._negative = negative
|
||||
self._file = file
|
||||
self._line = line
|
||||
}
|
||||
|
||||
public var withTimeout: (NSTimeInterval) -> NMBExpectation {
|
||||
return ({ timeout in self._timeout = timeout
|
||||
return self
|
||||
})
|
||||
}
|
||||
|
||||
public var to: (matcher: NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
expect(file: self._file, line: self._line){ self._actualBlock() as NSObject? }.to(
|
||||
ObjCMatcherWrapper(matcher: matcher, to: "to", toNot: "to not")
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public var toNot: (matcher: NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
expect(file: self._file, line: self._line){ self._actualBlock() as NSObject? }.toNot(
|
||||
ObjCMatcherWrapper(matcher: matcher, to: "to", toNot: "to not")
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public var notTo: (matcher: NMBMatcher) -> Void { return toNot }
|
||||
|
||||
public var toEventually: (matcher: NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
expect(file: self._file, line: self._line){ self._actualBlock() as NSObject? }.toEventually(
|
||||
ObjCMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"),
|
||||
timeout: self._timeout
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public var toEventuallyNot: (matcher: NMBMatcher) -> Void {
|
||||
return ({ matcher in
|
||||
expect(file: self._file, line: self._line){ self._actualBlock() as NSObject? }.toEventuallyNot(
|
||||
ObjCMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"),
|
||||
timeout: self._timeout
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
typealias MatcherBlock = (actualExpression: Expression<NSObject>, failureMessage: FailureMessage, location: SourceLocation) -> Bool
|
||||
typealias FullMatcherBlock = (actualExpression: Expression<NSObject>, failureMessage: FailureMessage, location: SourceLocation, shouldNotMatch: Bool) -> Bool
|
||||
@objc public class NMBObjCMatcher : NMBMatcher {
|
||||
let _match: MatcherBlock
|
||||
let _doesNotMatch: MatcherBlock
|
||||
let canMatchNil: Bool
|
||||
|
||||
init(canMatchNil: Bool, matcher: MatcherBlock, notMatcher: MatcherBlock) {
|
||||
self.canMatchNil = canMatchNil
|
||||
self._match = matcher
|
||||
self._doesNotMatch = notMatcher
|
||||
}
|
||||
|
||||
convenience init(matcher: MatcherBlock) {
|
||||
self.init(canMatchNil: true, matcher: matcher)
|
||||
}
|
||||
|
||||
convenience init(canMatchNil: Bool, matcher: MatcherBlock) {
|
||||
self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage, location in
|
||||
return !matcher(actualExpression: actualExpression, failureMessage: failureMessage, location: location)
|
||||
}))
|
||||
}
|
||||
|
||||
convenience init(matcher: FullMatcherBlock) {
|
||||
self.init(canMatchNil: true, matcher: matcher)
|
||||
}
|
||||
|
||||
convenience init(canMatchNil: Bool, matcher: FullMatcherBlock) {
|
||||
self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage, location in
|
||||
return matcher(actualExpression: actualExpression, failureMessage: failureMessage, location: location, shouldNotMatch: false)
|
||||
}), notMatcher: ({ actualExpression, failureMessage, location in
|
||||
return matcher(actualExpression: actualExpression, failureMessage: failureMessage, location: location, shouldNotMatch: true)
|
||||
}))
|
||||
}
|
||||
|
||||
private func canMatch(actualExpression: Expression<NSObject>, failureMessage: FailureMessage) -> Bool {
|
||||
if !canMatchNil && actualExpression.evaluate() == nil {
|
||||
failureMessage.postfixActual = " (use beNil() to match nils)"
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func matches(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let expr = Expression(expression: actualBlock, location: SourceLocation())
|
||||
let result = _match(
|
||||
actualExpression: expr,
|
||||
failureMessage: failureMessage,
|
||||
location: location)
|
||||
if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
|
||||
return result
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func doesNotMatch(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
|
||||
let expr = Expression(expression: actualBlock, location: SourceLocation())
|
||||
let result = _doesNotMatch(
|
||||
actualExpression: expr,
|
||||
failureMessage: failureMessage,
|
||||
location: location)
|
||||
if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
|
||||
return result
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class NMBExpectation;
|
||||
@class NMBObjCBeCloseToMatcher;
|
||||
@class NMBObjCRaiseExceptionMatcher;
|
||||
@protocol NMBMatcher;
|
||||
|
||||
|
||||
#define NIMBLE_EXPORT FOUNDATION_EXPORT
|
||||
|
||||
#ifdef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define NIMBLE_SHORT(PROTO, ORIGINAL)
|
||||
#else
|
||||
#define NIMBLE_SHORT(PROTO, ORIGINAL) FOUNDATION_STATIC_INLINE PROTO { return (ORIGINAL); }
|
||||
#endif
|
||||
|
||||
NIMBLE_EXPORT NMBExpectation *NMB_expect(id(^actualBlock)(), const char *file, unsigned int line);
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_equal(id expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> equal(id expectedValue),
|
||||
NMB_equal(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT(NMBObjCBeCloseToMatcher *beCloseTo(id expectedValue),
|
||||
NMB_beCloseTo(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAnInstanceOf(Class expectedClass);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beAnInstanceOf(Class expectedClass),
|
||||
NMB_beAnInstanceOf(expectedClass));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAKindOf(Class expectedClass);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beAKindOf(Class expectedClass),
|
||||
NMB_beAKindOf(expectedClass));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beginWith(id itemElementOrSubstring);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beginWith(id itemElementOrSubstring),
|
||||
NMB_beginWith(itemElementOrSubstring));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beGreaterThan(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beGreaterThan(NSNumber *expectedValue),
|
||||
NMB_beGreaterThan(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beGreaterThanOrEqualTo(NSNumber *expectedValue),
|
||||
NMB_beGreaterThanOrEqualTo(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beIdenticalTo(id expectedInstance);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beIdenticalTo(id expectedInstance),
|
||||
NMB_beIdenticalTo(expectedInstance));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beLessThan(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beLessThan(NSNumber *expectedValue),
|
||||
NMB_beLessThan(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beLessThanOrEqualTo(NSNumber *expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beLessThanOrEqualTo(NSNumber *expectedValue),
|
||||
NMB_beLessThanOrEqualTo(expectedValue));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTruthy(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beTruthy(void),
|
||||
NMB_beTruthy());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalsy(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beFalsy(void),
|
||||
NMB_beFalsy());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTrue(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beTrue(void),
|
||||
NMB_beTrue());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalse(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beFalse(void),
|
||||
NMB_beFalse());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beNil(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beNil(void),
|
||||
NMB_beNil());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beEmpty(void);
|
||||
NIMBLE_SHORT(id<NMBMatcher> beEmpty(void),
|
||||
NMB_beEmpty());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_contain(id itemOrSubstring);
|
||||
NIMBLE_SHORT(id<NMBMatcher> contain(id itemOrSubstring),
|
||||
NMB_contain(itemOrSubstring));
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_endWith(id itemElementOrSubstring);
|
||||
NIMBLE_SHORT(id<NMBMatcher> endWith(id itemElementOrSubstring),
|
||||
NMB_endWith(itemElementOrSubstring));
|
||||
|
||||
NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException(void);
|
||||
NIMBLE_SHORT(NMBObjCRaiseExceptionMatcher *raiseException(void),
|
||||
NMB_raiseException());
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_match(id expectedValue);
|
||||
NIMBLE_SHORT(id<NMBMatcher> match(id expectedValue),
|
||||
NMB_match(expectedValue));
|
||||
|
||||
// In order to preserve breakpoint behavior despite using macros to fill in __FILE__ and __LINE__,
|
||||
// define a builder that populates __FILE__ and __LINE__, and returns a block that takes timeout
|
||||
// and action arguments. See https://github.com/Quick/Quick/pull/185 for details.
|
||||
typedef void (^NMBWaitUntilTimeoutBlock)(NSTimeInterval timeout, void (^action)(void (^)(void)));
|
||||
typedef void (^NMBWaitUntilBlock)(void (^action)(void (^)(void)));
|
||||
|
||||
NIMBLE_EXPORT NMBWaitUntilTimeoutBlock nmb_wait_until_timeout_builder(NSString *file, NSUInteger line);
|
||||
NIMBLE_EXPORT NMBWaitUntilBlock nmb_wait_until_builder(NSString *file, NSUInteger line);
|
||||
|
||||
#define NMB_waitUntilTimeout nmb_wait_until_timeout_builder(@(__FILE__), __LINE__)
|
||||
#define NMB_waitUntil nmb_wait_until_builder(@(__FILE__), __LINE__)
|
||||
|
||||
#ifndef NIMBLE_DISABLE_SHORT_SYNTAX
|
||||
#define expect(...) NMB_expect(^id{ return (__VA_ARGS__); }, __FILE__, __LINE__)
|
||||
#define expectAction(...) NMB_expect(^id{ (__VA_ARGS__); return nil; }, __FILE__, __LINE__)
|
||||
#define waitUntilTimeout NMB_waitUntilTimeout
|
||||
#define waitUntil NMB_waitUntil
|
||||
#endif
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#import <Nimble/DSL.h>
|
||||
#import <Nimble/Nimble-Swift.h>
|
||||
|
||||
NIMBLE_EXPORT NMBExpectation *NMB_expect(id(^actualBlock)(), const char *file, unsigned int line) {
|
||||
return [[NMBExpectation alloc] initWithActualBlock:actualBlock
|
||||
negative:NO
|
||||
file:[[NSString alloc] initWithFormat:@"%s", file]
|
||||
line:line];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAnInstanceOf(Class expectedClass) {
|
||||
return [NMBObjCMatcher beAnInstanceOfMatcher:expectedClass];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beAKindOf(Class expectedClass) {
|
||||
return [NMBObjCMatcher beAKindOfMatcher:expectedClass];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT NMBObjCBeCloseToMatcher *NMB_beCloseTo(NSNumber *expectedValue) {
|
||||
return [NMBObjCMatcher beCloseToMatcher:expectedValue within:0.001];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beginWith(id itemElementOrSubstring) {
|
||||
return [NMBObjCMatcher beginWithMatcher:itemElementOrSubstring];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beGreaterThan(NSNumber *expectedValue) {
|
||||
return [NMBObjCMatcher beGreaterThanMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beGreaterThanOrEqualTo(NSNumber *expectedValue) {
|
||||
return [NMBObjCMatcher beGreaterThanOrEqualToMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beIdenticalTo(id expectedInstance) {
|
||||
return [NMBObjCMatcher beIdenticalToMatcher:expectedInstance];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beLessThan(NSNumber *expectedValue) {
|
||||
return [NMBObjCMatcher beLessThanMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beLessThanOrEqualTo(NSNumber *expectedValue) {
|
||||
return [NMBObjCMatcher beLessThanOrEqualToMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTruthy() {
|
||||
return [NMBObjCMatcher beTruthyMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalsy() {
|
||||
return [NMBObjCMatcher beFalsyMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beTrue() {
|
||||
return [NMBObjCMatcher beTrueMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalse() {
|
||||
return [NMBObjCMatcher beFalseMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beNil() {
|
||||
return [NMBObjCMatcher beNilMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_beEmpty() {
|
||||
return [NMBObjCMatcher beEmptyMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_contain(id itemOrSubstring) {
|
||||
return [NMBObjCMatcher containMatcher:itemOrSubstring];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_endWith(id itemElementOrSubstring) {
|
||||
return [NMBObjCMatcher endWithMatcher:itemElementOrSubstring];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_equal(id expectedValue) {
|
||||
return [NMBObjCMatcher equalMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT id<NMBMatcher> NMB_match(id expectedValue) {
|
||||
return [NMBObjCMatcher matchMatcher:expectedValue];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT NMBObjCRaiseExceptionMatcher *NMB_raiseException() {
|
||||
return [NMBObjCMatcher raiseExceptionMatcher];
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT NMBWaitUntilTimeoutBlock nmb_wait_until_timeout_builder(NSString *file, NSUInteger line) {
|
||||
return ^(NSTimeInterval timeout, void (^action)(void (^)(void))) {
|
||||
[NMBWait untilTimeout:timeout action:action file:file line:line];
|
||||
};
|
||||
}
|
||||
|
||||
NIMBLE_EXPORT NMBWaitUntilBlock nmb_wait_until_builder(NSString *file, NSUInteger line) {
|
||||
return ^(void (^action)(void (^)(void))) {
|
||||
[NMBWait until:action file:file line:line];
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NMBExceptionCapture : NSObject
|
||||
|
||||
- (id)initWithHandler:(void(^)(NSException *))handler finally:(void(^)())finally;
|
||||
- (void)tryBlock:(void(^)())unsafeBlock;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#import "NMBExceptionCapture.h"
|
||||
|
||||
@interface NMBExceptionCapture ()
|
||||
@property (nonatomic, copy) void(^handler)(NSException *exception);
|
||||
@property (nonatomic, copy) void(^finally)();
|
||||
@end
|
||||
|
||||
@implementation NMBExceptionCapture
|
||||
|
||||
- (id)initWithHandler:(void(^)(NSException *))handler finally:(void(^)())finally {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.handler = handler;
|
||||
self.finally = finally;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)tryBlock:(void(^)())unsafeBlock {
|
||||
@try {
|
||||
unsafeBlock();
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
if (self.handler) {
|
||||
self.handler(exception);
|
||||
}
|
||||
}
|
||||
@finally {
|
||||
if (self.finally) {
|
||||
self.finally();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,913 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
063E8FF4CDFCA6AE9064115D /* Match.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0532F94D7DEF51D97275BFBE /* Match.swift */; };
|
||||
0C1C88128A14FB102A244FB2 /* Pods-cameraTests-Nimble-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 82048FF5F5EFF9305672C391 /* Pods-cameraTests-Nimble-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
0DE457D3E7DBE1ACD5C3D501 /* Functional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF2111C551AF9DB8E1EF0D4 /* Functional.swift */; };
|
||||
148835A4D3AFD1C2E5AD45B3 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 402ACB04DB1A0D5DFD74F095 /* Expression.swift */; };
|
||||
1DA17DDB55A971E2DCE64EC1 /* Callsite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EEF62B2DD8F00333107ABD5 /* Callsite.swift */; };
|
||||
1E5F0C6E0DDCFCD7F013E317 /* Pods-cameraTests-Nimble-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2563F2959D17BA2558043577 /* Pods-cameraTests-Nimble-dummy.m */; };
|
||||
2045ABFCB6047AAABAFD5951 /* NonNilMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA0C0BEF285D56CF99F9BAFF /* NonNilMatcherWrapper.swift */; };
|
||||
215CFF9F5CAFD9259A55DAA8 /* Stringers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD33B1DB349F34B4254F41C8 /* Stringers.swift */; };
|
||||
24EC168BC53587C5BAA31DF8 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D25C7D9460041796229179A6 /* DSL.swift */; };
|
||||
2583C08B2B578208A1F3EF74 /* BeLogical.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471D38845FE2712C8D24E2B2 /* BeLogical.swift */; };
|
||||
29767E33FB320295213ED819 /* Pods-cameraTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F41DDB356DAEA5AE9D68F607 /* Pods-cameraTests-dummy.m */; };
|
||||
2B03C1417FFA9C18A8AB1AA0 /* Pods-cameraTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 319B45E19AE5060F26A16C98 /* Pods-cameraTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2C78C1C5EE6B462D3F98C015 /* BeGreaterThanOrEqualTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2F7037B987C74A3ED1EBFB /* BeGreaterThanOrEqualTo.swift */; };
|
||||
2DD2E38C9E6579166798FEDF /* Nimble.h in Headers */ = {isa = PBXBuildFile; fileRef = B20D631CE4DCBF504E55A2AE /* Nimble.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
31F138AF892521818A7A24DB /* DSL+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC533250C6B34D3F73A8823 /* DSL+Wait.swift */; };
|
||||
4285DB510E4C2975EC76AB63 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFFBC02BB9B8B3867FC27FD8 /* Foundation.framework */; };
|
||||
44983BE29EC5942CA81CC746 /* ExampleMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7E8C66E5FDC940E269FA8EE /* ExampleMetadata.swift */; };
|
||||
4588F215C7B4D62EB6D25B65 /* NSString+QCKSelectorName.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B396785B7F6615196840BDF /* NSString+QCKSelectorName.m */; };
|
||||
469FB027B28EA5637451BCDA /* BeNil.swift in Sources */ = {isa = PBXBuildFile; fileRef = C198515AF8C48951047C3943 /* BeNil.swift */; };
|
||||
47D9B38EC06F0C2D754B30E8 /* BeEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CED32A84A0D0848A31C737 /* BeEmpty.swift */; };
|
||||
4C8ACE662BA5A7740E9837F7 /* AsyncMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB89177296F437C09E320EBB /* AsyncMatcherWrapper.swift */; };
|
||||
55DDF0B03E9424CFFC3AF509 /* QuickSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 20E1F52A34452E4FA8C09B97 /* QuickSpec.m */; };
|
||||
566FBD2A832342493B5E1248 /* Closures.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB09B9D379670E585AC1A13F /* Closures.swift */; };
|
||||
5C2D96298D8C523D2D26EB3D /* QuickConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 60F89AACA3CF3565890BBE49 /* QuickConfiguration.m */; };
|
||||
5CAF4ACE6BA1C7452395D6A9 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 162A7C8BEFEDFC011A49B88B /* XCTest.framework */; };
|
||||
5DADA0D163D6F2AB97923636 /* BeIdenticalTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505291DF2F3F7BAEC5C13A9A /* BeIdenticalTo.swift */; };
|
||||
6E0F5AECCF6F03172F05E212 /* NMBExceptionCapture.h in Headers */ = {isa = PBXBuildFile; fileRef = FE29350F14BE8900985973C3 /* NMBExceptionCapture.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
6FBFFFC70B42C58008662472 /* ExampleHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D05A5AECA35165DB51FF23C /* ExampleHooks.swift */; };
|
||||
805F293C8EBCB8B9DF9A72C3 /* Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = A38C289E43ECD26E8939591E /* Poll.swift */; };
|
||||
83B6D03B51245190D8231710 /* QuickSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = C282D3D28C0BEC2EBC15A8DF /* QuickSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8530A93B446712333274DC5C /* Pods-cameraTests-Quick-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D55D3DF99DE7681A2BF29E48 /* Pods-cameraTests-Quick-dummy.m */; };
|
||||
88941222651EFD5099091A80 /* AdapterProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8630A26F9BAB2A785161489 /* AdapterProtocols.swift */; };
|
||||
89BA35CC59B06F790F4FB74B /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB281C3837A207CC43C4BC7D /* World.swift */; };
|
||||
8F595832DC35B61579EE169E /* BeLessThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C3A8A501FDD021511871A68 /* BeLessThan.swift */; };
|
||||
90A1E3E113A4854CDE879B7A /* ObjCMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08D659BCCBEE7E6D07689459 /* ObjCMatcher.swift */; };
|
||||
916B0B420F40CBBE80F1D53E /* Failure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F975D83EBDA345C8FFF01E3 /* Failure.swift */; };
|
||||
91B8BA9DB5971B966053E3C7 /* MatcherFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA3099BFB4185F0F9767377 /* MatcherFunc.swift */; };
|
||||
969C23D06E4FA1F290FE3246 /* SuiteHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2389619E50745E53C4B52528 /* SuiteHooks.swift */; };
|
||||
97D0996C4D453390EC72FB74 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFFBC02BB9B8B3867FC27FD8 /* Foundation.framework */; };
|
||||
9A32003B9A5212D5DB5DD242 /* NSString+QCKSelectorName.h in Headers */ = {isa = PBXBuildFile; fileRef = DB8A4880FEBDC35E69C45749 /* NSString+QCKSelectorName.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
A0855A9E298477B377CCED81 /* DSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C5228EE1BA2EEDDFE07798C /* DSL.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
A0CA0C07D5BC4D70CD1CFA7F /* ExampleGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023EDA9E6B95AB5CEC4B4486 /* ExampleGroup.swift */; };
|
||||
A3A73AA2DE52892441B7C07B /* World+DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B618EB76AF4D043BB1CB23D5 /* World+DSL.swift */; };
|
||||
A53A614EA359BE4BC5E7A76F /* SourceLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 521FFDC3BB0D3ACFAFB152C5 /* SourceLocation.swift */; };
|
||||
AC5A06E42BB74303D071D511 /* QCKDSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E6B9FF0BCC8962A6C65076A /* QCKDSL.m */; };
|
||||
B140E0F3305E9B616E69FE43 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15DD6B442275C14CAE3A1B66 /* Example.swift */; };
|
||||
B3AA544E38464E781C8CC293 /* FullMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10AAD1CDC0D3F5F3811E373F /* FullMatcherWrapper.swift */; };
|
||||
B456F2687494679DCC788F13 /* BeAnInstanceOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8EA6DCEF3F2E5E57BF215C /* BeAnInstanceOf.swift */; };
|
||||
B4B2AE2237712BD5C19B0118 /* Quick.h in Headers */ = {isa = PBXBuildFile; fileRef = A2E5E3720B0C95643A807292 /* Quick.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C4BFDF7E8990139CB496F329 /* BeAKindOf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9518ECD232456850752F53A9 /* BeAKindOf.swift */; };
|
||||
C7C750539B66C4A25629C408 /* XCTestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CCDAA183DD8D7743EA56A62 /* XCTestHandler.swift */; };
|
||||
CEED31385D717D6650D6215B /* QuickConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 4ED460346C47D3AFFC6090B8 /* QuickConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D0571DA54BC746097B7E24DD /* Contain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B2BB9B92C8802E08894181 /* Contain.swift */; };
|
||||
D222320726C05BFAA57F4125 /* Pods-cameraTests-Quick-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D035D62A299B43E1A25EC5 /* Pods-cameraTests-Quick-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D24F4280730F62EBA770A466 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 162A7C8BEFEDFC011A49B88B /* XCTest.framework */; };
|
||||
D4F6891916948345C4F34CB3 /* BeLessThanOrEqual.swift in Sources */ = {isa = PBXBuildFile; fileRef = 101E03BF1A34E5E7AF543F36 /* BeLessThanOrEqual.swift */; };
|
||||
DAC661C91F943606AAA50D08 /* QCKDSL.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D1A8FF83A07B9D8E0829FF /* QCKDSL.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DAE797E73B09B1BC1949905F /* Equal.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAE50AB5F905197F46BD849C /* Equal.swift */; };
|
||||
DD4A57F896D7155C9288D542 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317BE5243B6AF2E8548397AA /* Configuration.swift */; };
|
||||
DEE1E683E8D1993467BD5A04 /* BeGreaterThan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 950BF84666ADF1BEDBD288E4 /* BeGreaterThan.swift */; };
|
||||
DF251E97102A9CA07892ADD9 /* EndWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C1AD18150646E02B4BA2B8 /* EndWith.swift */; };
|
||||
E5405948B5668C7744B2B500 /* RaisesException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2998B2ADD9C42625B07F3AFF /* RaisesException.swift */; };
|
||||
E6B6A48E6BECCE0DFD34E181 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C2C0AF2677DB9CAC6E081C /* MatcherProtocols.swift */; };
|
||||
E6D1ADBA50F5D37ED62DF0D0 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC12C064DC64767DF335152E /* Filter.swift */; };
|
||||
E92D205A4BFDC48A341C5303 /* NMBExceptionCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = CC8571A8C022144BCE3CA10A /* NMBExceptionCapture.m */; };
|
||||
E9FB65406B698DDAA6049113 /* BeginWith.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E16B6CB02D5174AFB2978EE /* BeginWith.swift */; };
|
||||
EA787861C31E6CF172E606A1 /* BasicMatcherWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F79813906738A2BD6AA38B /* BasicMatcherWrapper.swift */; };
|
||||
ED6EE4512210821BD4A7CCE5 /* Expectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927BE526BA3C7C60EC6D1167 /* Expectation.swift */; };
|
||||
EEB52C99E3DBDD83F1358174 /* DSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D826AAF28238AA855ABA32D0 /* DSL.swift */; };
|
||||
EEB7CEB54D7A73B5D6880666 /* DSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 1873C187F1C5BFEDF74A6BA3 /* DSL.m */; };
|
||||
EF0A2ACC9641B96FF65447F6 /* BeCloseTo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C83946110D73E44EF4F81113 /* BeCloseTo.swift */; };
|
||||
F024FD314F49ABBFB66A44D1 /* AssertionRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33F8FE546E76EC71E1B4C24A /* AssertionRecorder.swift */; };
|
||||
F9A9F02544CEC452A4EC300D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFFBC02BB9B8B3867FC27FD8 /* Foundation.framework */; };
|
||||
FA95CE02552C5BE7B6B28522 /* FailureMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7218266BAAFAEDFC4DEED9E5 /* FailureMessage.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
37D85D4EDDBAF1915445F71D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 937304FB055E8B31CCE17C33 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 03098993B86EADB31B473BE6;
|
||||
remoteInfo = "Pods-cameraTests-Nimble";
|
||||
};
|
||||
7CA981DCCC17BAE34B95333C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 937304FB055E8B31CCE17C33 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 63EE31CFA4335E182795B62C;
|
||||
remoteInfo = "Pods-cameraTests-Quick";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
012CF5B0C5FAFA77ED64A0D1 /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
|
||||
023EDA9E6B95AB5CEC4B4486 /* ExampleGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleGroup.swift; path = Quick/ExampleGroup.swift; sourceTree = "<group>"; };
|
||||
04C98A932ACA82234342D315 /* Pods-cameraTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-cameraTests-acknowledgements.plist"; sourceTree = "<group>"; };
|
||||
0532F94D7DEF51D97275BFBE /* Match.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Match.swift; path = Nimble/Matchers/Match.swift; sourceTree = "<group>"; };
|
||||
069BE081A378991AC5D4C293 /* Pods-cameraTests-Quick.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-cameraTests-Quick.modulemap"; sourceTree = "<group>"; };
|
||||
08D659BCCBEE7E6D07689459 /* ObjCMatcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ObjCMatcher.swift; path = Nimble/Wrappers/ObjCMatcher.swift; sourceTree = "<group>"; };
|
||||
0AE7F2DBC9CCBE4489BA75DE /* Pods-cameraTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-cameraTests-acknowledgements.markdown"; sourceTree = "<group>"; };
|
||||
0E16B6CB02D5174AFB2978EE /* BeginWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeginWith.swift; path = Nimble/Matchers/BeginWith.swift; sourceTree = "<group>"; };
|
||||
101E03BF1A34E5E7AF543F36 /* BeLessThanOrEqual.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThanOrEqual.swift; path = Nimble/Matchers/BeLessThanOrEqual.swift; sourceTree = "<group>"; };
|
||||
10AAD1CDC0D3F5F3811E373F /* FullMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FullMatcherWrapper.swift; path = Nimble/Wrappers/FullMatcherWrapper.swift; sourceTree = "<group>"; };
|
||||
10D035D62A299B43E1A25EC5 /* Pods-cameraTests-Quick-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-Quick-umbrella.h"; sourceTree = "<group>"; };
|
||||
15DD6B442275C14CAE3A1B66 /* Example.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Example.swift; path = Quick/Example.swift; sourceTree = "<group>"; };
|
||||
15F79813906738A2BD6AA38B /* BasicMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BasicMatcherWrapper.swift; path = Nimble/Wrappers/BasicMatcherWrapper.swift; sourceTree = "<group>"; };
|
||||
162A7C8BEFEDFC011A49B88B /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
|
||||
17C2C0AF2677DB9CAC6E081C /* MatcherProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherProtocols.swift; path = Nimble/Matchers/MatcherProtocols.swift; sourceTree = "<group>"; };
|
||||
1873C187F1C5BFEDF74A6BA3 /* DSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = DSL.m; path = Nimble/objc/DSL.m; sourceTree = "<group>"; };
|
||||
19609E67865F88C862DF57F9 /* Pods-cameraTests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-cameraTests-resources.sh"; sourceTree = "<group>"; };
|
||||
1C3A8A501FDD021511871A68 /* BeLessThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLessThan.swift; path = Nimble/Matchers/BeLessThan.swift; sourceTree = "<group>"; };
|
||||
1CA3099BFB4185F0F9767377 /* MatcherFunc.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MatcherFunc.swift; path = Nimble/Wrappers/MatcherFunc.swift; sourceTree = "<group>"; };
|
||||
1D8EA6DCEF3F2E5E57BF215C /* BeAnInstanceOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAnInstanceOf.swift; path = Nimble/Matchers/BeAnInstanceOf.swift; sourceTree = "<group>"; };
|
||||
20E1F52A34452E4FA8C09B97 /* QuickSpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickSpec.m; path = Quick/QuickSpec.m; sourceTree = "<group>"; };
|
||||
2389619E50745E53C4B52528 /* SuiteHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SuiteHooks.swift; path = Quick/Hooks/SuiteHooks.swift; sourceTree = "<group>"; };
|
||||
2563F2959D17BA2558043577 /* Pods-cameraTests-Nimble-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-cameraTests-Nimble-dummy.m"; sourceTree = "<group>"; };
|
||||
28C1AD18150646E02B4BA2B8 /* EndWith.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EndWith.swift; path = Nimble/Matchers/EndWith.swift; sourceTree = "<group>"; };
|
||||
295C9B81917E2E66C4CB585F /* Pods-cameraTests-environment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-environment.h"; sourceTree = "<group>"; };
|
||||
2998B2ADD9C42625B07F3AFF /* RaisesException.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RaisesException.swift; path = Nimble/Matchers/RaisesException.swift; sourceTree = "<group>"; };
|
||||
2DF2111C551AF9DB8E1EF0D4 /* Functional.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Functional.swift; path = Nimble/Utils/Functional.swift; sourceTree = "<group>"; };
|
||||
2E83D4416070EF016A049329 /* Pods-cameraTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
317BE5243B6AF2E8548397AA /* Configuration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Configuration.swift; path = Quick/Configuration/Configuration.swift; sourceTree = "<group>"; };
|
||||
319B45E19AE5060F26A16C98 /* Pods-cameraTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-umbrella.h"; sourceTree = "<group>"; };
|
||||
32D1A8FF83A07B9D8E0829FF /* QCKDSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QCKDSL.h; path = Quick/DSL/QCKDSL.h; sourceTree = "<group>"; };
|
||||
33F8FE546E76EC71E1B4C24A /* AssertionRecorder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertionRecorder.swift; path = Nimble/Adapters/AssertionRecorder.swift; sourceTree = "<group>"; };
|
||||
3793683F5C9C8923253EC1D9 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
3C5228EE1BA2EEDDFE07798C /* DSL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = DSL.h; path = Nimble/objc/DSL.h; sourceTree = "<group>"; };
|
||||
402ACB04DB1A0D5DFD74F095 /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = Nimble/Expression.swift; sourceTree = "<group>"; };
|
||||
45B2BB9B92C8802E08894181 /* Contain.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Contain.swift; path = Nimble/Matchers/Contain.swift; sourceTree = "<group>"; };
|
||||
471D38845FE2712C8D24E2B2 /* BeLogical.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeLogical.swift; path = Nimble/Matchers/BeLogical.swift; sourceTree = "<group>"; };
|
||||
4BA526DB9E85C442548416FF /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4ED460346C47D3AFFC6090B8 /* QuickConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickConfiguration.h; path = Quick/Configuration/QuickConfiguration.h; sourceTree = "<group>"; };
|
||||
505291DF2F3F7BAEC5C13A9A /* BeIdenticalTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeIdenticalTo.swift; path = Nimble/Matchers/BeIdenticalTo.swift; sourceTree = "<group>"; };
|
||||
521FFDC3BB0D3ACFAFB152C5 /* SourceLocation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceLocation.swift; path = Nimble/Utils/SourceLocation.swift; sourceTree = "<group>"; };
|
||||
5B396785B7F6615196840BDF /* NSString+QCKSelectorName.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSString+QCKSelectorName.m"; path = "Quick/NSString+QCKSelectorName.m"; sourceTree = "<group>"; };
|
||||
60F89AACA3CF3565890BBE49 /* QuickConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QuickConfiguration.m; path = Quick/Configuration/QuickConfiguration.m; sourceTree = "<group>"; };
|
||||
6759F6DB7C918DCA172362CB /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
6E6B9FF0BCC8962A6C65076A /* QCKDSL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QCKDSL.m; path = Quick/DSL/QCKDSL.m; sourceTree = "<group>"; };
|
||||
7218266BAAFAEDFC4DEED9E5 /* FailureMessage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FailureMessage.swift; path = Nimble/FailureMessage.swift; sourceTree = "<group>"; };
|
||||
7B748F87FF3D770DF9007604 /* Quick.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7DE5D16EBDF47FE756EFDD5F /* Pods-cameraTests-Nimble.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests-Nimble.xcconfig"; sourceTree = "<group>"; };
|
||||
7EEF62B2DD8F00333107ABD5 /* Callsite.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Callsite.swift; path = Quick/Callsite.swift; sourceTree = "<group>"; };
|
||||
7FD9B1694D7D39B422068BF9 /* Pods-cameraTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
82048FF5F5EFF9305672C391 /* Pods-cameraTests-Nimble-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-Nimble-umbrella.h"; sourceTree = "<group>"; };
|
||||
87EC112C5F1B702FC4B3F370 /* Pods-cameraTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-cameraTests.modulemap"; sourceTree = "<group>"; };
|
||||
8D91B6199A9DEBE41D2FDA21 /* Pods_cameraTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_cameraTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8DDAB2D1C38A94C6D032404C /* Pods-cameraTests-Quick-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-Quick-prefix.pch"; sourceTree = "<group>"; };
|
||||
8EC533250C6B34D3F73A8823 /* DSL+Wait.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "DSL+Wait.swift"; path = "Nimble/DSL+Wait.swift"; sourceTree = "<group>"; };
|
||||
8F2F7037B987C74A3ED1EBFB /* BeGreaterThanOrEqualTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThanOrEqualTo.swift; path = Nimble/Matchers/BeGreaterThanOrEqualTo.swift; sourceTree = "<group>"; };
|
||||
927BE526BA3C7C60EC6D1167 /* Expectation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expectation.swift; path = Nimble/Expectation.swift; sourceTree = "<group>"; };
|
||||
950BF84666ADF1BEDBD288E4 /* BeGreaterThan.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeGreaterThan.swift; path = Nimble/Matchers/BeGreaterThan.swift; sourceTree = "<group>"; };
|
||||
9518ECD232456850752F53A9 /* BeAKindOf.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeAKindOf.swift; path = Nimble/Matchers/BeAKindOf.swift; sourceTree = "<group>"; };
|
||||
9CCDAA183DD8D7743EA56A62 /* XCTestHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = XCTestHandler.swift; path = Nimble/Adapters/XCTestHandler.swift; sourceTree = "<group>"; };
|
||||
9D05A5AECA35165DB51FF23C /* ExampleHooks.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleHooks.swift; path = Quick/Hooks/ExampleHooks.swift; sourceTree = "<group>"; };
|
||||
9F975D83EBDA345C8FFF01E3 /* Failure.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Failure.swift; path = Quick/Failure.swift; sourceTree = "<group>"; };
|
||||
A2E5E3720B0C95643A807292 /* Quick.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Quick.h; path = Quick/Quick.h; sourceTree = "<group>"; };
|
||||
A38C289E43ECD26E8939591E /* Poll.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Poll.swift; path = Nimble/Utils/Poll.swift; sourceTree = "<group>"; };
|
||||
A8630A26F9BAB2A785161489 /* AdapterProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AdapterProtocols.swift; path = Nimble/Adapters/AdapterProtocols.swift; sourceTree = "<group>"; };
|
||||
AE55690197160BABCF839CF6 /* Pods-cameraTests-Nimble-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests-Nimble-Private.xcconfig"; sourceTree = "<group>"; };
|
||||
AFFBC02BB9B8B3867FC27FD8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||
B08C633FA95B2863036438B9 /* Pods-cameraTests-Quick.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests-Quick.xcconfig"; sourceTree = "<group>"; };
|
||||
B20D631CE4DCBF504E55A2AE /* Nimble.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Nimble.h; path = Nimble/Nimble.h; sourceTree = "<group>"; };
|
||||
B618EB76AF4D043BB1CB23D5 /* World+DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "World+DSL.swift"; path = "Quick/DSL/World+DSL.swift"; sourceTree = "<group>"; };
|
||||
B7E8C66E5FDC940E269FA8EE /* ExampleMetadata.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExampleMetadata.swift; path = Quick/ExampleMetadata.swift; sourceTree = "<group>"; };
|
||||
BB09B9D379670E585AC1A13F /* Closures.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Closures.swift; path = Quick/Hooks/Closures.swift; sourceTree = "<group>"; };
|
||||
BB281C3837A207CC43C4BC7D /* World.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = World.swift; path = Quick/World.swift; sourceTree = "<group>"; };
|
||||
BD33B1DB349F34B4254F41C8 /* Stringers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Stringers.swift; path = Nimble/Utils/Stringers.swift; sourceTree = "<group>"; };
|
||||
BFEE86CD156B011635A2DCFD /* Pods-cameraTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-cameraTests-frameworks.sh"; sourceTree = "<group>"; };
|
||||
C198515AF8C48951047C3943 /* BeNil.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeNil.swift; path = Nimble/Matchers/BeNil.swift; sourceTree = "<group>"; };
|
||||
C282D3D28C0BEC2EBC15A8DF /* QuickSpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = QuickSpec.h; path = Quick/QuickSpec.h; sourceTree = "<group>"; };
|
||||
C83946110D73E44EF4F81113 /* BeCloseTo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeCloseTo.swift; path = Nimble/Matchers/BeCloseTo.swift; sourceTree = "<group>"; };
|
||||
CC8571A8C022144BCE3CA10A /* NMBExceptionCapture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = NMBExceptionCapture.m; path = Nimble/objc/NMBExceptionCapture.m; sourceTree = "<group>"; };
|
||||
D25C7D9460041796229179A6 /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Nimble/DSL.swift; sourceTree = "<group>"; };
|
||||
D2CED32A84A0D0848A31C737 /* BeEmpty.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BeEmpty.swift; path = Nimble/Matchers/BeEmpty.swift; sourceTree = "<group>"; };
|
||||
D55D3DF99DE7681A2BF29E48 /* Pods-cameraTests-Quick-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-cameraTests-Quick-dummy.m"; sourceTree = "<group>"; };
|
||||
D826AAF28238AA855ABA32D0 /* DSL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DSL.swift; path = Quick/DSL/DSL.swift; sourceTree = "<group>"; };
|
||||
DA0C0BEF285D56CF99F9BAFF /* NonNilMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NonNilMatcherWrapper.swift; path = Nimble/Wrappers/NonNilMatcherWrapper.swift; sourceTree = "<group>"; };
|
||||
DB89177296F437C09E320EBB /* AsyncMatcherWrapper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AsyncMatcherWrapper.swift; path = Nimble/Wrappers/AsyncMatcherWrapper.swift; sourceTree = "<group>"; };
|
||||
DB8A4880FEBDC35E69C45749 /* NSString+QCKSelectorName.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSString+QCKSelectorName.h"; path = "Quick/NSString+QCKSelectorName.h"; sourceTree = "<group>"; };
|
||||
DFE1A82827C4DC004907D038 /* Pods-cameraTests-Quick-Private.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-cameraTests-Quick-Private.xcconfig"; sourceTree = "<group>"; };
|
||||
EB54E115C989CF89C6F59FDF /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F41DDB356DAEA5AE9D68F607 /* Pods-cameraTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-cameraTests-dummy.m"; sourceTree = "<group>"; };
|
||||
F5A2611FED51DF823BD66EFD /* Pods-cameraTests-Nimble.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-cameraTests-Nimble.modulemap"; sourceTree = "<group>"; };
|
||||
F65674506659FCBD087F62FE /* Pods-cameraTests-Nimble-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-cameraTests-Nimble-prefix.pch"; sourceTree = "<group>"; };
|
||||
FAE50AB5F905197F46BD849C /* Equal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Equal.swift; path = Nimble/Matchers/Equal.swift; sourceTree = "<group>"; };
|
||||
FC12C064DC64767DF335152E /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Quick/Filter.swift; sourceTree = "<group>"; };
|
||||
FE29350F14BE8900985973C3 /* NMBExceptionCapture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = NMBExceptionCapture.h; path = Nimble/objc/NMBExceptionCapture.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
58094DDE21DBB51BC835A4A4 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F9A9F02544CEC452A4EC300D /* Foundation.framework in Frameworks */,
|
||||
5CAF4ACE6BA1C7452395D6A9 /* XCTest.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6B1C7242D21308F1279EA301 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97D0996C4D453390EC72FB74 /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
71C74F61879210D969B8CFF5 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4285DB510E4C2975EC76AB63 /* Foundation.framework in Frameworks */,
|
||||
D24F4280730F62EBA770A466 /* XCTest.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08F881C603574785D738721C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
012CF5B0C5FAFA77ED64A0D1 /* Podfile */,
|
||||
B15D4557820AE99A4D342CB4 /* Frameworks */,
|
||||
957D697A04C144323B10B143 /* Pods */,
|
||||
B1E20CDBA0845824CB7F7AD0 /* Products */,
|
||||
EB6DD5BB32A1AE1C45DA962C /* Targets Support Files */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3AD18E3BF6AE65FDD211F642 /* Nimble */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A8630A26F9BAB2A785161489 /* AdapterProtocols.swift */,
|
||||
33F8FE546E76EC71E1B4C24A /* AssertionRecorder.swift */,
|
||||
DB89177296F437C09E320EBB /* AsyncMatcherWrapper.swift */,
|
||||
15F79813906738A2BD6AA38B /* BasicMatcherWrapper.swift */,
|
||||
9518ECD232456850752F53A9 /* BeAKindOf.swift */,
|
||||
1D8EA6DCEF3F2E5E57BF215C /* BeAnInstanceOf.swift */,
|
||||
C83946110D73E44EF4F81113 /* BeCloseTo.swift */,
|
||||
D2CED32A84A0D0848A31C737 /* BeEmpty.swift */,
|
||||
950BF84666ADF1BEDBD288E4 /* BeGreaterThan.swift */,
|
||||
8F2F7037B987C74A3ED1EBFB /* BeGreaterThanOrEqualTo.swift */,
|
||||
505291DF2F3F7BAEC5C13A9A /* BeIdenticalTo.swift */,
|
||||
1C3A8A501FDD021511871A68 /* BeLessThan.swift */,
|
||||
101E03BF1A34E5E7AF543F36 /* BeLessThanOrEqual.swift */,
|
||||
471D38845FE2712C8D24E2B2 /* BeLogical.swift */,
|
||||
C198515AF8C48951047C3943 /* BeNil.swift */,
|
||||
0E16B6CB02D5174AFB2978EE /* BeginWith.swift */,
|
||||
45B2BB9B92C8802E08894181 /* Contain.swift */,
|
||||
3C5228EE1BA2EEDDFE07798C /* DSL.h */,
|
||||
1873C187F1C5BFEDF74A6BA3 /* DSL.m */,
|
||||
D25C7D9460041796229179A6 /* DSL.swift */,
|
||||
8EC533250C6B34D3F73A8823 /* DSL+Wait.swift */,
|
||||
28C1AD18150646E02B4BA2B8 /* EndWith.swift */,
|
||||
FAE50AB5F905197F46BD849C /* Equal.swift */,
|
||||
927BE526BA3C7C60EC6D1167 /* Expectation.swift */,
|
||||
402ACB04DB1A0D5DFD74F095 /* Expression.swift */,
|
||||
7218266BAAFAEDFC4DEED9E5 /* FailureMessage.swift */,
|
||||
10AAD1CDC0D3F5F3811E373F /* FullMatcherWrapper.swift */,
|
||||
2DF2111C551AF9DB8E1EF0D4 /* Functional.swift */,
|
||||
0532F94D7DEF51D97275BFBE /* Match.swift */,
|
||||
1CA3099BFB4185F0F9767377 /* MatcherFunc.swift */,
|
||||
17C2C0AF2677DB9CAC6E081C /* MatcherProtocols.swift */,
|
||||
FE29350F14BE8900985973C3 /* NMBExceptionCapture.h */,
|
||||
CC8571A8C022144BCE3CA10A /* NMBExceptionCapture.m */,
|
||||
B20D631CE4DCBF504E55A2AE /* Nimble.h */,
|
||||
DA0C0BEF285D56CF99F9BAFF /* NonNilMatcherWrapper.swift */,
|
||||
08D659BCCBEE7E6D07689459 /* ObjCMatcher.swift */,
|
||||
A38C289E43ECD26E8939591E /* Poll.swift */,
|
||||
2998B2ADD9C42625B07F3AFF /* RaisesException.swift */,
|
||||
521FFDC3BB0D3ACFAFB152C5 /* SourceLocation.swift */,
|
||||
BD33B1DB349F34B4254F41C8 /* Stringers.swift */,
|
||||
9CCDAA183DD8D7743EA56A62 /* XCTestHandler.swift */,
|
||||
C579C6A6E4BEE85A4FB9E7E3 /* Support Files */,
|
||||
);
|
||||
path = Nimble;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
53F4DB2DDDF3FC1008E4F3FC /* Quick */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7EEF62B2DD8F00333107ABD5 /* Callsite.swift */,
|
||||
BB09B9D379670E585AC1A13F /* Closures.swift */,
|
||||
317BE5243B6AF2E8548397AA /* Configuration.swift */,
|
||||
D826AAF28238AA855ABA32D0 /* DSL.swift */,
|
||||
15DD6B442275C14CAE3A1B66 /* Example.swift */,
|
||||
023EDA9E6B95AB5CEC4B4486 /* ExampleGroup.swift */,
|
||||
9D05A5AECA35165DB51FF23C /* ExampleHooks.swift */,
|
||||
B7E8C66E5FDC940E269FA8EE /* ExampleMetadata.swift */,
|
||||
9F975D83EBDA345C8FFF01E3 /* Failure.swift */,
|
||||
FC12C064DC64767DF335152E /* Filter.swift */,
|
||||
DB8A4880FEBDC35E69C45749 /* NSString+QCKSelectorName.h */,
|
||||
5B396785B7F6615196840BDF /* NSString+QCKSelectorName.m */,
|
||||
32D1A8FF83A07B9D8E0829FF /* QCKDSL.h */,
|
||||
6E6B9FF0BCC8962A6C65076A /* QCKDSL.m */,
|
||||
A2E5E3720B0C95643A807292 /* Quick.h */,
|
||||
4ED460346C47D3AFFC6090B8 /* QuickConfiguration.h */,
|
||||
60F89AACA3CF3565890BBE49 /* QuickConfiguration.m */,
|
||||
C282D3D28C0BEC2EBC15A8DF /* QuickSpec.h */,
|
||||
20E1F52A34452E4FA8C09B97 /* QuickSpec.m */,
|
||||
2389619E50745E53C4B52528 /* SuiteHooks.swift */,
|
||||
BB281C3837A207CC43C4BC7D /* World.swift */,
|
||||
B618EB76AF4D043BB1CB23D5 /* World+DSL.swift */,
|
||||
EED5FEA1196A4D1AF951C4CE /* Support Files */,
|
||||
);
|
||||
path = Quick;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
957D697A04C144323B10B143 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3AD18E3BF6AE65FDD211F642 /* Nimble */,
|
||||
53F4DB2DDDF3FC1008E4F3FC /* Quick */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A9B4B57B53606BB9CE6EB5BC /* Pods-cameraTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6759F6DB7C918DCA172362CB /* Info.plist */,
|
||||
87EC112C5F1B702FC4B3F370 /* Pods-cameraTests.modulemap */,
|
||||
0AE7F2DBC9CCBE4489BA75DE /* Pods-cameraTests-acknowledgements.markdown */,
|
||||
04C98A932ACA82234342D315 /* Pods-cameraTests-acknowledgements.plist */,
|
||||
F41DDB356DAEA5AE9D68F607 /* Pods-cameraTests-dummy.m */,
|
||||
295C9B81917E2E66C4CB585F /* Pods-cameraTests-environment.h */,
|
||||
BFEE86CD156B011635A2DCFD /* Pods-cameraTests-frameworks.sh */,
|
||||
19609E67865F88C862DF57F9 /* Pods-cameraTests-resources.sh */,
|
||||
319B45E19AE5060F26A16C98 /* Pods-cameraTests-umbrella.h */,
|
||||
7FD9B1694D7D39B422068BF9 /* Pods-cameraTests.debug.xcconfig */,
|
||||
2E83D4416070EF016A049329 /* Pods-cameraTests.release.xcconfig */,
|
||||
);
|
||||
name = "Pods-cameraTests";
|
||||
path = "Target Support Files/Pods-cameraTests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B15D4557820AE99A4D342CB4 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E12DDD9F4BE1C635F8E8936D /* iOS */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1E20CDBA0845824CB7F7AD0 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BA526DB9E85C442548416FF /* Nimble.framework */,
|
||||
8D91B6199A9DEBE41D2FDA21 /* Pods_cameraTests.framework */,
|
||||
7B748F87FF3D770DF9007604 /* Quick.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C579C6A6E4BEE85A4FB9E7E3 /* Support Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3793683F5C9C8923253EC1D9 /* Info.plist */,
|
||||
F5A2611FED51DF823BD66EFD /* Pods-cameraTests-Nimble.modulemap */,
|
||||
7DE5D16EBDF47FE756EFDD5F /* Pods-cameraTests-Nimble.xcconfig */,
|
||||
AE55690197160BABCF839CF6 /* Pods-cameraTests-Nimble-Private.xcconfig */,
|
||||
2563F2959D17BA2558043577 /* Pods-cameraTests-Nimble-dummy.m */,
|
||||
F65674506659FCBD087F62FE /* Pods-cameraTests-Nimble-prefix.pch */,
|
||||
82048FF5F5EFF9305672C391 /* Pods-cameraTests-Nimble-umbrella.h */,
|
||||
);
|
||||
name = "Support Files";
|
||||
path = "../Target Support Files/Pods-cameraTests-Nimble";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E12DDD9F4BE1C635F8E8936D /* iOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AFFBC02BB9B8B3867FC27FD8 /* Foundation.framework */,
|
||||
162A7C8BEFEDFC011A49B88B /* XCTest.framework */,
|
||||
);
|
||||
name = iOS;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EB6DD5BB32A1AE1C45DA962C /* Targets Support Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A9B4B57B53606BB9CE6EB5BC /* Pods-cameraTests */,
|
||||
);
|
||||
name = "Targets Support Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EED5FEA1196A4D1AF951C4CE /* Support Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EB54E115C989CF89C6F59FDF /* Info.plist */,
|
||||
069BE081A378991AC5D4C293 /* Pods-cameraTests-Quick.modulemap */,
|
||||
B08C633FA95B2863036438B9 /* Pods-cameraTests-Quick.xcconfig */,
|
||||
DFE1A82827C4DC004907D038 /* Pods-cameraTests-Quick-Private.xcconfig */,
|
||||
D55D3DF99DE7681A2BF29E48 /* Pods-cameraTests-Quick-dummy.m */,
|
||||
8DDAB2D1C38A94C6D032404C /* Pods-cameraTests-Quick-prefix.pch */,
|
||||
10D035D62A299B43E1A25EC5 /* Pods-cameraTests-Quick-umbrella.h */,
|
||||
);
|
||||
name = "Support Files";
|
||||
path = "../Target Support Files/Pods-cameraTests-Quick";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
A5BB95D35970C3C680F429C2 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A0855A9E298477B377CCED81 /* DSL.h in Headers */,
|
||||
6E0F5AECCF6F03172F05E212 /* NMBExceptionCapture.h in Headers */,
|
||||
2DD2E38C9E6579166798FEDF /* Nimble.h in Headers */,
|
||||
0C1C88128A14FB102A244FB2 /* Pods-cameraTests-Nimble-umbrella.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A9AF48F077E44AB8816A6B3A /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2B03C1417FFA9C18A8AB1AA0 /* Pods-cameraTests-umbrella.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
B667064B3F9530CEE1FE0A09 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A32003B9A5212D5DB5DD242 /* NSString+QCKSelectorName.h in Headers */,
|
||||
D222320726C05BFAA57F4125 /* Pods-cameraTests-Quick-umbrella.h in Headers */,
|
||||
DAC661C91F943606AAA50D08 /* QCKDSL.h in Headers */,
|
||||
B4B2AE2237712BD5C19B0118 /* Quick.h in Headers */,
|
||||
CEED31385D717D6650D6215B /* QuickConfiguration.h in Headers */,
|
||||
83B6D03B51245190D8231710 /* QuickSpec.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
03098993B86EADB31B473BE6 /* Pods-cameraTests-Nimble */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = BB79BEC5BA1769570BD1E7DD /* Build configuration list for PBXNativeTarget "Pods-cameraTests-Nimble" */;
|
||||
buildPhases = (
|
||||
763398E741FB1E12C12D84F2 /* Sources */,
|
||||
71C74F61879210D969B8CFF5 /* Frameworks */,
|
||||
A5BB95D35970C3C680F429C2 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Pods-cameraTests-Nimble";
|
||||
productName = "Pods-cameraTests-Nimble";
|
||||
productReference = 4BA526DB9E85C442548416FF /* Nimble.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
13DE2AA1E6F090FB14C78F4F /* Pods-cameraTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 5E163F4741EBD5093FF979A0 /* Build configuration list for PBXNativeTarget "Pods-cameraTests" */;
|
||||
buildPhases = (
|
||||
A44FD4D3C268FE6ABFB86370 /* Sources */,
|
||||
6B1C7242D21308F1279EA301 /* Frameworks */,
|
||||
A9AF48F077E44AB8816A6B3A /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
5A3678F527D62842A8BE1355 /* PBXTargetDependency */,
|
||||
CB41BD7C70E50072C531B672 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "Pods-cameraTests";
|
||||
productName = "Pods-cameraTests";
|
||||
productReference = 8D91B6199A9DEBE41D2FDA21 /* Pods_cameraTests.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
63EE31CFA4335E182795B62C /* Pods-cameraTests-Quick */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 80E8FCBE643252A34AECC2C1 /* Build configuration list for PBXNativeTarget "Pods-cameraTests-Quick" */;
|
||||
buildPhases = (
|
||||
1295A3CC72F95948B0E41FFA /* Sources */,
|
||||
58094DDE21DBB51BC835A4A4 /* Frameworks */,
|
||||
B667064B3F9530CEE1FE0A09 /* Headers */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Pods-cameraTests-Quick";
|
||||
productName = "Pods-cameraTests-Quick";
|
||||
productReference = 7B748F87FF3D770DF9007604 /* Quick.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
937304FB055E8B31CCE17C33 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0510;
|
||||
};
|
||||
buildConfigurationList = 5769F664A8E3A93FFCE45473 /* Build configuration list for PBXProject "Pods" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 08F881C603574785D738721C;
|
||||
productRefGroup = B1E20CDBA0845824CB7F7AD0 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13DE2AA1E6F090FB14C78F4F /* Pods-cameraTests */,
|
||||
03098993B86EADB31B473BE6 /* Pods-cameraTests-Nimble */,
|
||||
63EE31CFA4335E182795B62C /* Pods-cameraTests-Quick */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
1295A3CC72F95948B0E41FFA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1DA17DDB55A971E2DCE64EC1 /* Callsite.swift in Sources */,
|
||||
566FBD2A832342493B5E1248 /* Closures.swift in Sources */,
|
||||
DD4A57F896D7155C9288D542 /* Configuration.swift in Sources */,
|
||||
EEB52C99E3DBDD83F1358174 /* DSL.swift in Sources */,
|
||||
B140E0F3305E9B616E69FE43 /* Example.swift in Sources */,
|
||||
A0CA0C07D5BC4D70CD1CFA7F /* ExampleGroup.swift in Sources */,
|
||||
6FBFFFC70B42C58008662472 /* ExampleHooks.swift in Sources */,
|
||||
44983BE29EC5942CA81CC746 /* ExampleMetadata.swift in Sources */,
|
||||
916B0B420F40CBBE80F1D53E /* Failure.swift in Sources */,
|
||||
E6D1ADBA50F5D37ED62DF0D0 /* Filter.swift in Sources */,
|
||||
4588F215C7B4D62EB6D25B65 /* NSString+QCKSelectorName.m in Sources */,
|
||||
8530A93B446712333274DC5C /* Pods-cameraTests-Quick-dummy.m in Sources */,
|
||||
AC5A06E42BB74303D071D511 /* QCKDSL.m in Sources */,
|
||||
5C2D96298D8C523D2D26EB3D /* QuickConfiguration.m in Sources */,
|
||||
55DDF0B03E9424CFFC3AF509 /* QuickSpec.m in Sources */,
|
||||
969C23D06E4FA1F290FE3246 /* SuiteHooks.swift in Sources */,
|
||||
A3A73AA2DE52892441B7C07B /* World+DSL.swift in Sources */,
|
||||
89BA35CC59B06F790F4FB74B /* World.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
763398E741FB1E12C12D84F2 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
88941222651EFD5099091A80 /* AdapterProtocols.swift in Sources */,
|
||||
F024FD314F49ABBFB66A44D1 /* AssertionRecorder.swift in Sources */,
|
||||
4C8ACE662BA5A7740E9837F7 /* AsyncMatcherWrapper.swift in Sources */,
|
||||
EA787861C31E6CF172E606A1 /* BasicMatcherWrapper.swift in Sources */,
|
||||
C4BFDF7E8990139CB496F329 /* BeAKindOf.swift in Sources */,
|
||||
B456F2687494679DCC788F13 /* BeAnInstanceOf.swift in Sources */,
|
||||
EF0A2ACC9641B96FF65447F6 /* BeCloseTo.swift in Sources */,
|
||||
47D9B38EC06F0C2D754B30E8 /* BeEmpty.swift in Sources */,
|
||||
DEE1E683E8D1993467BD5A04 /* BeGreaterThan.swift in Sources */,
|
||||
2C78C1C5EE6B462D3F98C015 /* BeGreaterThanOrEqualTo.swift in Sources */,
|
||||
5DADA0D163D6F2AB97923636 /* BeIdenticalTo.swift in Sources */,
|
||||
8F595832DC35B61579EE169E /* BeLessThan.swift in Sources */,
|
||||
D4F6891916948345C4F34CB3 /* BeLessThanOrEqual.swift in Sources */,
|
||||
2583C08B2B578208A1F3EF74 /* BeLogical.swift in Sources */,
|
||||
469FB027B28EA5637451BCDA /* BeNil.swift in Sources */,
|
||||
E9FB65406B698DDAA6049113 /* BeginWith.swift in Sources */,
|
||||
D0571DA54BC746097B7E24DD /* Contain.swift in Sources */,
|
||||
31F138AF892521818A7A24DB /* DSL+Wait.swift in Sources */,
|
||||
EEB7CEB54D7A73B5D6880666 /* DSL.m in Sources */,
|
||||
24EC168BC53587C5BAA31DF8 /* DSL.swift in Sources */,
|
||||
DF251E97102A9CA07892ADD9 /* EndWith.swift in Sources */,
|
||||
DAE797E73B09B1BC1949905F /* Equal.swift in Sources */,
|
||||
ED6EE4512210821BD4A7CCE5 /* Expectation.swift in Sources */,
|
||||
148835A4D3AFD1C2E5AD45B3 /* Expression.swift in Sources */,
|
||||
FA95CE02552C5BE7B6B28522 /* FailureMessage.swift in Sources */,
|
||||
B3AA544E38464E781C8CC293 /* FullMatcherWrapper.swift in Sources */,
|
||||
0DE457D3E7DBE1ACD5C3D501 /* Functional.swift in Sources */,
|
||||
063E8FF4CDFCA6AE9064115D /* Match.swift in Sources */,
|
||||
91B8BA9DB5971B966053E3C7 /* MatcherFunc.swift in Sources */,
|
||||
E6B6A48E6BECCE0DFD34E181 /* MatcherProtocols.swift in Sources */,
|
||||
E92D205A4BFDC48A341C5303 /* NMBExceptionCapture.m in Sources */,
|
||||
2045ABFCB6047AAABAFD5951 /* NonNilMatcherWrapper.swift in Sources */,
|
||||
90A1E3E113A4854CDE879B7A /* ObjCMatcher.swift in Sources */,
|
||||
1E5F0C6E0DDCFCD7F013E317 /* Pods-cameraTests-Nimble-dummy.m in Sources */,
|
||||
805F293C8EBCB8B9DF9A72C3 /* Poll.swift in Sources */,
|
||||
E5405948B5668C7744B2B500 /* RaisesException.swift in Sources */,
|
||||
A53A614EA359BE4BC5E7A76F /* SourceLocation.swift in Sources */,
|
||||
215CFF9F5CAFD9259A55DAA8 /* Stringers.swift in Sources */,
|
||||
C7C750539B66C4A25629C408 /* XCTestHandler.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A44FD4D3C268FE6ABFB86370 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
29767E33FB320295213ED819 /* Pods-cameraTests-dummy.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
5A3678F527D62842A8BE1355 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "Pods-cameraTests-Nimble";
|
||||
target = 03098993B86EADB31B473BE6 /* Pods-cameraTests-Nimble */;
|
||||
targetProxy = 37D85D4EDDBAF1915445F71D /* PBXContainerItemProxy */;
|
||||
};
|
||||
CB41BD7C70E50072C531B672 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "Pods-cameraTests-Quick";
|
||||
target = 63EE31CFA4335E182795B62C /* Pods-cameraTests-Quick */;
|
||||
targetProxy = 7CA981DCCC17BAE34B95333C /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00239A09BAF338DE4756F37E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7FD9B1694D7D39B422068BF9 /* Pods-cameraTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests/Pods-cameraTests.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_NAME = Pods_cameraTests;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1B091D115A0C1092280F7931 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = DFE1A82827C4DC004907D038 /* Pods-cameraTests-Quick-Private.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_PREFIX_HEADER = "Target Support Files/Pods-cameraTests-Quick/Pods-cameraTests-Quick-prefix.pch";
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests-Quick/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests-Quick/Pods-cameraTests-Quick.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = Quick;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
20B00DF98765E75714720D04 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
SYMROOT = "${SRCROOT}/../build";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
3C81ABF0EA0FFD687A137559 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AE55690197160BABCF839CF6 /* Pods-cameraTests-Nimble-Private.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_PREFIX_HEADER = "Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-prefix.pch";
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests-Nimble/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9E796F71A1E7451766EAB9AE /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AE55690197160BABCF839CF6 /* Pods-cameraTests-Nimble-Private.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_PREFIX_HEADER = "Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-prefix.pch";
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests-Nimble/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = Nimble;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C6871B2830DDCE0A1BA3E7E4 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 2E83D4416070EF016A049329 /* Pods-cameraTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests/Pods-cameraTests.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_NAME = Pods_cameraTests;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DA520EE373392C6DFDFD3B98 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = DFE1A82827C4DC004907D038 /* Pods-cameraTests-Quick-Private.xcconfig */;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_PREFIX_HEADER = "Target Support Files/Pods-cameraTests-Quick/Pods-cameraTests-Quick-prefix.pch";
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-cameraTests-Quick/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-cameraTests-Quick/Pods-cameraTests-Quick.modulemap";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = Quick;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
FFC7600F9623F21509735F5F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
SYMROOT = "${SRCROOT}/../build";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
5769F664A8E3A93FFCE45473 /* Build configuration list for PBXProject "Pods" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
FFC7600F9623F21509735F5F /* Debug */,
|
||||
20B00DF98765E75714720D04 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
5E163F4741EBD5093FF979A0 /* Build configuration list for PBXNativeTarget "Pods-cameraTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00239A09BAF338DE4756F37E /* Debug */,
|
||||
C6871B2830DDCE0A1BA3E7E4 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
80E8FCBE643252A34AECC2C1 /* Build configuration list for PBXNativeTarget "Pods-cameraTests-Quick" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DA520EE373392C6DFDFD3B98 /* Debug */,
|
||||
1B091D115A0C1092280F7931 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
BB79BEC5BA1769570BD1E7DD /* Build configuration list for PBXNativeTarget "Pods-cameraTests-Nimble" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
3C81ABF0EA0FFD687A137559 /* Debug */,
|
||||
9E796F71A1E7451766EAB9AE /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 937304FB055E8B31CCE17C33 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "03098993B86EADB31B473BE6"
|
||||
BuildableName = "Nimble.framework"
|
||||
BlueprintName = "Pods-cameraTests-Nimble"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
59
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/Pods-cameraTests-Quick.xcscheme
generated
Normal file
59
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/Pods-cameraTests-Quick.xcscheme
generated
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "63EE31CFA4335E182795B62C"
|
||||
BuildableName = "Quick.framework"
|
||||
BlueprintName = "Pods-cameraTests-Quick"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
59
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/Pods-cameraTests.xcscheme
generated
Normal file
59
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/Pods-cameraTests.xcscheme
generated
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13DE2AA1E6F090FB14C78F4F"
|
||||
BuildableName = "Pods_cameraTests.framework"
|
||||
BlueprintName = "Pods-cameraTests"
|
||||
ReferencedContainer = "container:Pods.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
42
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/xcschememanagement.plist
generated
Normal file
42
Pods/Pods.xcodeproj/xcuserdata/nataliaterlecka.xcuserdatad/xcschemes/xcschememanagement.plist
generated
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Pods-cameraTests-Nimble.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<key>Pods-cameraTests-Quick.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<key>Pods-cameraTests.xcscheme</key>
|
||||
<dict>
|
||||
<key>isShown</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>03098993B86EADB31B473BE6</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>13DE2AA1E6F090FB14C78F4F</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>63EE31CFA4335E182795B62C</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014, Quick Team
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
An object encapsulating the file and line number at which
|
||||
a particular example is defined.
|
||||
*/
|
||||
@objc final public class Callsite: Equatable {
|
||||
/**
|
||||
The absolute path of the file in which an example is defined.
|
||||
*/
|
||||
public let file: String
|
||||
|
||||
/**
|
||||
The line number on which an example is defined.
|
||||
*/
|
||||
public let line: Int
|
||||
|
||||
internal init(file: String, line: Int) {
|
||||
self.file = file
|
||||
self.line = line
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a boolean indicating whether two Callsite objects are equal.
|
||||
If two callsites are in the same file and on the same line, they must be equal.
|
||||
*/
|
||||
public func ==(lhs: Callsite, rhs: Callsite) -> Bool {
|
||||
return lhs.file == rhs.file && lhs.line == rhs.line
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/**
|
||||
A closure that temporarily exposes a Configuration object within
|
||||
the scope of the closure.
|
||||
*/
|
||||
public typealias QuickConfigurer = (configuration: Configuration) -> ()
|
||||
|
||||
/**
|
||||
A closure that, given metadata about an example, returns a boolean value
|
||||
indicating whether that example should be run.
|
||||
*/
|
||||
public typealias ExampleFilter = (example: Example) -> Bool
|
||||
|
||||
/**
|
||||
A configuration encapsulates various options you can use
|
||||
to configure Quick's behavior.
|
||||
*/
|
||||
@objc final public class Configuration {
|
||||
internal let exampleHooks = ExampleHooks()
|
||||
internal let suiteHooks = SuiteHooks()
|
||||
internal var exclusionFilters: [ExampleFilter] = [{ example in
|
||||
if let pending = example.filterFlags[Filter.pending] {
|
||||
return pending
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}]
|
||||
internal var inclusionFilters: [ExampleFilter] = [{ example in
|
||||
if let focused = example.filterFlags[Filter.focused] {
|
||||
return focused
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}]
|
||||
|
||||
/**
|
||||
Run all examples if none match the configured filters. True by default.
|
||||
*/
|
||||
public var runAllWhenEverythingFiltered = true
|
||||
|
||||
/**
|
||||
Registers an inclusion filter.
|
||||
|
||||
All examples are filtered using all inclusion filters.
|
||||
The remaining examples are run. If no examples remain, all examples are run.
|
||||
|
||||
:param: filter A filter that, given an example, returns a value indicating
|
||||
whether that example should be included in the examples
|
||||
that are run.
|
||||
*/
|
||||
public func include(filter: ExampleFilter) {
|
||||
inclusionFilters.append(filter)
|
||||
}
|
||||
|
||||
/**
|
||||
Registers an exclusion filter.
|
||||
|
||||
All examples that remain after being filtered by the inclusion filters are
|
||||
then filtered via all exclusion filters.
|
||||
|
||||
:param: filter A filter that, given an example, returns a value indicating
|
||||
whether that example should be excluded from the examples
|
||||
that are run.
|
||||
*/
|
||||
public func exclude(filter: ExampleFilter) {
|
||||
exclusionFilters.append(filter)
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to Quick.Configuration.beforeEach, except the closure is
|
||||
provided with metadata on the example that the closure is being run
|
||||
prior to.
|
||||
*/
|
||||
@objc(beforeEachWithMetadata:)
|
||||
public func beforeEach(closure: BeforeExampleWithMetadataClosure) {
|
||||
exampleHooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Like Quick.DSL.beforeEach, this configures Quick to execute the
|
||||
given closure before each example that is run. The closure
|
||||
passed to this method is executed before each example Quick runs,
|
||||
globally across the test suite. You may call this method multiple
|
||||
times across mulitple +[QuickConfigure configure:] methods in order
|
||||
to define several closures to run before each example.
|
||||
|
||||
Note that, since Quick makes no guarantee as to the order in which
|
||||
+[QuickConfiguration configure:] methods are evaluated, there is no
|
||||
guarantee as to the order in which beforeEach closures are evaluated
|
||||
either. Mulitple beforeEach defined on a single configuration, however,
|
||||
will be executed in the order they're defined.
|
||||
|
||||
:param: closure The closure to be executed before each example
|
||||
in the test suite.
|
||||
*/
|
||||
public func beforeEach(closure: BeforeExampleClosure) {
|
||||
exampleHooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to Quick.Configuration.afterEach, except the closure
|
||||
is provided with metadata on the example that the closure is being
|
||||
run after.
|
||||
*/
|
||||
@objc(afterEachWithMetadata:)
|
||||
public func afterEach(closure: AfterExampleWithMetadataClosure) {
|
||||
exampleHooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Like Quick.DSL.afterEach, this configures Quick to execute the
|
||||
given closure after each example that is run. The closure
|
||||
passed to this method is executed after each example Quick runs,
|
||||
globally across the test suite. You may call this method multiple
|
||||
times across mulitple +[QuickConfigure configure:] methods in order
|
||||
to define several closures to run after each example.
|
||||
|
||||
Note that, since Quick makes no guarantee as to the order in which
|
||||
+[QuickConfiguration configure:] methods are evaluated, there is no
|
||||
guarantee as to the order in which afterEach closures are evaluated
|
||||
either. Mulitple afterEach defined on a single configuration, however,
|
||||
will be executed in the order they're defined.
|
||||
|
||||
:param: closure The closure to be executed before each example
|
||||
in the test suite.
|
||||
*/
|
||||
public func afterEach(closure: AfterExampleClosure) {
|
||||
exampleHooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Like Quick.DSL.beforeSuite, this configures Quick to execute
|
||||
the given closure prior to any and all examples that are run.
|
||||
The two methods are functionally equivalent.
|
||||
*/
|
||||
public func beforeSuite(closure: BeforeSuiteClosure) {
|
||||
suiteHooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Like Quick.DSL.afterSuite, this configures Quick to execute
|
||||
the given closure after all examples have been run.
|
||||
The two methods are functionally equivalent.
|
||||
*/
|
||||
public func afterSuite(closure: AfterSuiteClosure) {
|
||||
suiteHooks.appendAfter(closure)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class Configuration;
|
||||
|
||||
/**
|
||||
Subclass QuickConfiguration and override the +[QuickConfiguration configure:]
|
||||
method in order to configure how Quick behaves when running specs, or to define
|
||||
shared examples that are used across spec files.
|
||||
*/
|
||||
@interface QuickConfiguration : NSObject
|
||||
|
||||
/**
|
||||
This method is executed on each subclass of this class before Quick runs
|
||||
any examples. You may override this method on as many subclasses as you like, but
|
||||
there is no guarantee as to the order in which these methods are executed.
|
||||
|
||||
You can override this method in order to:
|
||||
|
||||
1. Configure how Quick behaves, by modifying properties on the Configuration object.
|
||||
Setting the same properties in several methods has undefined behavior.
|
||||
|
||||
2. Define shared examples using `sharedExamples`.
|
||||
|
||||
@param configuration A mutable object that is used to configure how Quick behaves on
|
||||
a framework level. For details on all the options, see the
|
||||
documentation in Configuration.swift.
|
||||
*/
|
||||
+ (void)configure:(Configuration *)configuration;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#import "QuickConfiguration.h"
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
typedef void (^QCKClassEnumerationBlock)(Class klass);
|
||||
|
||||
/**
|
||||
Finds all direct subclasses of the given class and passes them to the block provided.
|
||||
The classes are iterated over in the order that objc_getClassList returns them.
|
||||
|
||||
@param klass The base class to find subclasses of.
|
||||
@param block A block that takes a Class. This block will be executed once for each subclass of klass.
|
||||
*/
|
||||
void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) {
|
||||
Class *classes = NULL;
|
||||
int classesCount = objc_getClassList(NULL, 0);
|
||||
|
||||
if (classesCount > 0) {
|
||||
classes = (Class *)calloc(sizeof(Class), classesCount);
|
||||
classesCount = objc_getClassList(classes, classesCount);
|
||||
|
||||
Class subclass, superclass;
|
||||
for(int i = 0; i < classesCount; i++) {
|
||||
subclass = classes[i];
|
||||
superclass = class_getSuperclass(subclass);
|
||||
if (superclass == klass && block) {
|
||||
block(subclass);
|
||||
}
|
||||
}
|
||||
|
||||
free(classes);
|
||||
}
|
||||
}
|
||||
|
||||
@implementation QuickConfiguration
|
||||
|
||||
#pragma mark - Object Lifecycle
|
||||
|
||||
/**
|
||||
QuickConfiguration is not meant to be instantiated; it merely provides a hook
|
||||
for users to configure how Quick behaves. Raise an exception if an instance of
|
||||
QuickConfiguration is created.
|
||||
*/
|
||||
- (instancetype)init {
|
||||
NSString *className = NSStringFromClass([self class]);
|
||||
NSString *selectorName = NSStringFromSelector(@selector(configure:));
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"%@ is not meant to be instantiated; "
|
||||
@"subclass %@ and override %@ to configure Quick.",
|
||||
className, className, selectorName];
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - NSObject Overrides
|
||||
|
||||
/**
|
||||
Hook into when QuickConfiguration is initialized in the runtime in order to
|
||||
call +[QuickConfiguration configure:] on each of its subclasses.
|
||||
*/
|
||||
+ (void)initialize {
|
||||
// Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses.
|
||||
if ([self class] == [QuickConfiguration class]) {
|
||||
|
||||
// Only enumerate over subclasses once, even if +[QuickConfiguration initialize]
|
||||
// were to be called several times. This is necessary because +[QuickSpec initialize]
|
||||
// manually calls +[QuickConfiguration initialize].
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) {
|
||||
[[World sharedWorld] configure:^(Configuration *configuration) {
|
||||
[klass configure:configuration];
|
||||
}];
|
||||
});
|
||||
[[World sharedWorld] finalizeConfiguration];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Public Interface
|
||||
|
||||
+ (void)configure:(Configuration *)configuration { }
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
Defines a closure to be run prior to any examples in the test suite.
|
||||
You may define an unlimited number of these closures, but there is no
|
||||
guarantee as to the order in which they're run.
|
||||
|
||||
If the test suite crashes before the first example is run, this closure
|
||||
will not be executed.
|
||||
|
||||
:param: closure The closure to be run prior to any examples in the test suite.
|
||||
*/
|
||||
public func beforeSuite(closure: BeforeSuiteClosure) {
|
||||
World.sharedWorld().beforeSuite(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a closure to be run after all of the examples in the test suite.
|
||||
You may define an unlimited number of these closures, but there is no
|
||||
guarantee as to the order in which they're run.
|
||||
|
||||
If the test suite crashes before all examples are run, this closure
|
||||
will not be executed.
|
||||
|
||||
:param: closure The closure to be run after all of the examples in the test suite.
|
||||
*/
|
||||
public func afterSuite(closure: AfterSuiteClosure) {
|
||||
World.sharedWorld().afterSuite(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a group of shared examples. These examples can be re-used in several locations
|
||||
by using the `itBehavesLike` function.
|
||||
|
||||
:param: name The name of the shared example group. This must be unique across all shared example
|
||||
groups defined in a test suite.
|
||||
:param: closure A closure containing the examples. This behaves just like an example group defined
|
||||
using `describe` or `context`--the closure may contain any number of `beforeEach`
|
||||
and `afterEach` closures, as well as any number of examples (defined using `it`).
|
||||
*/
|
||||
public func sharedExamples(name: String, closure: () -> ()) {
|
||||
World.sharedWorld().sharedExamples(name, closure: { (NSDictionary) in closure() })
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a group of shared examples. These examples can be re-used in several locations
|
||||
by using the `itBehavesLike` function.
|
||||
|
||||
:param: name The name of the shared example group. This must be unique across all shared example
|
||||
groups defined in a test suite.
|
||||
:param: closure A closure containing the examples. This behaves just like an example group defined
|
||||
using `describe` or `context`--the closure may contain any number of `beforeEach`
|
||||
and `afterEach` closures, as well as any number of examples (defined using `it`).
|
||||
|
||||
The closure takes a SharedExampleContext as an argument. This context is a function
|
||||
that can be executed to retrieve parameters passed in via an `itBehavesLike` function.
|
||||
*/
|
||||
public func sharedExamples(name: String, closure: SharedExampleClosure) {
|
||||
World.sharedWorld().sharedExamples(name, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example group. Example groups are logical groupings of examples.
|
||||
Example groups can share setup and teardown code.
|
||||
|
||||
:param: description An arbitrary string describing the example group.
|
||||
:param: closure A closure that can contain other examples.
|
||||
:param: flags A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
*/
|
||||
public func describe(description: String, closure: () -> (), flags: FilterFlags = [:]) {
|
||||
World.sharedWorld().describe(description, closure: closure, flags: flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example group. Equivalent to `describe`.
|
||||
*/
|
||||
public func context(description: String, closure: () -> (), flags: FilterFlags = [:]) {
|
||||
describe(description, closure, flags: flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a closure to be run prior to each example in the current example
|
||||
group. This closure is not run for pending or otherwise disabled examples.
|
||||
An example group may contain an unlimited number of beforeEach. They'll be
|
||||
run in the order they're defined, but you shouldn't rely on that behavior.
|
||||
|
||||
:param: closure The closure to be run prior to each example.
|
||||
*/
|
||||
public func beforeEach(closure: BeforeExampleClosure) {
|
||||
World.sharedWorld().beforeEach(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to Quick.DSL.beforeEach, except the closure is provided with
|
||||
metadata on the example that the closure is being run prior to.
|
||||
*/
|
||||
public func beforeEach(#closure: BeforeExampleWithMetadataClosure) {
|
||||
World.sharedWorld().beforeEach(closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a closure to be run after each example in the current example
|
||||
group. This closure is not run for pending or otherwise disabled examples.
|
||||
An example group may contain an unlimited number of afterEach. They'll be
|
||||
run in the order they're defined, but you shouldn't rely on that behavior.
|
||||
|
||||
:param: closure The closure to be run after each example.
|
||||
*/
|
||||
public func afterEach(closure: AfterExampleClosure) {
|
||||
World.sharedWorld().afterEach(closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to Quick.DSL.afterEach, except the closure is provided with
|
||||
metadata on the example that the closure is being run after.
|
||||
*/
|
||||
public func afterEach(#closure: AfterExampleWithMetadataClosure) {
|
||||
World.sharedWorld().afterEach(closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example. Examples use assertions to demonstrate how code should
|
||||
behave. These are like "tests" in XCTest.
|
||||
|
||||
:param: description An arbitrary string describing what the example is meant to specify.
|
||||
:param: closure A closure that can contain assertions.
|
||||
:param: flags A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
:param: file The absolute path to the file containing the example. A sensible default is provided.
|
||||
:param: line The line containing the example. A sensible default is provided.
|
||||
*/
|
||||
public func it(description: String, closure: () -> (), flags: FilterFlags = [:], file: String = __FILE__, line: Int = __LINE__) {
|
||||
World.sharedWorld().it(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts the examples defined using a `sharedExamples` function into the current example group.
|
||||
The shared examples are executed at this location, as if they were written out manually.
|
||||
|
||||
:param: name The name of the shared examples group to be executed. This must be identical to the
|
||||
name of a shared examples group defined using `sharedExamples`. If there are no shared
|
||||
examples that match the name given, an exception is thrown and the test suite will crash.
|
||||
:param: flags A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
:param: file The absolute path to the file containing the current example group. A sensible default is provided.
|
||||
:param: line The line containing the current example group. A sensible default is provided.
|
||||
*/
|
||||
public func itBehavesLike(name: String, flags: FilterFlags = [:], file: String = __FILE__, line: Int = __LINE__) {
|
||||
itBehavesLike(name, { return [:] }, flags: flags, file: file, line: line)
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts the examples defined using a `sharedExamples` function into the current example group.
|
||||
The shared examples are executed at this location, as if they were written out manually.
|
||||
This function also passes those shared examples a context that can be evaluated to give the shared
|
||||
examples extra information on the subject of the example.
|
||||
|
||||
:param: name The name of the shared examples group to be executed. This must be identical to the
|
||||
name of a shared examples group defined using `sharedExamples`. If there are no shared
|
||||
examples that match the name given, an exception is thrown and the test suite will crash.
|
||||
:param: sharedExampleContext A closure that, when evaluated, returns key-value pairs that provide the
|
||||
shared examples with extra information on the subject of the example.
|
||||
:param: flags A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
:param: file The absolute path to the file containing the current example group. A sensible default is provided.
|
||||
:param: line The line containing the current example group. A sensible default is provided.
|
||||
*/
|
||||
public func itBehavesLike(name: String, sharedExampleContext: SharedExampleContext, flags: FilterFlags = [:], file: String = __FILE__, line: Int = __LINE__) {
|
||||
World.sharedWorld().itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example or example group that should not be executed. Use `pending` to temporarily disable
|
||||
examples or groups that should not be run yet.
|
||||
|
||||
:param: description An arbitrary string describing the example or example group.
|
||||
:param: closure A closure that will not be evaluated.
|
||||
*/
|
||||
public func pending(description: String, closure: () -> ()) {
|
||||
World.sharedWorld().pending(description, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark a `describe` closure as pending.
|
||||
This disables all examples within the closure.
|
||||
*/
|
||||
public func xdescribe(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
World.sharedWorld().xdescribe(description, closure: closure, flags: flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark a `context` closure as pending.
|
||||
This disables all examples within the closure.
|
||||
*/
|
||||
public func xcontext(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
xdescribe(description, closure, flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark an `it` closure as pending.
|
||||
This disables the example and ensures the code within the closure is never run.
|
||||
*/
|
||||
public func xit(description: String, closure: () -> (), flags: FilterFlags = [:], file: String = __FILE__, line: Int = __LINE__) {
|
||||
World.sharedWorld().xit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus a `describe` closure, focusing the examples in the closure.
|
||||
If any examples in the test suite are focused, only those examples are executed.
|
||||
This trumps any explicitly focused or unfocused examples within the closure--they are all treated as focused.
|
||||
*/
|
||||
public func fdescribe(description: String, closure: () -> (), flags: FilterFlags = [:]) {
|
||||
World.sharedWorld().fdescribe(description, closure: closure, flags: flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus a `context` closure. Equivalent to `fdescribe`.
|
||||
*/
|
||||
public func fcontext(description: String, closure: () -> (), flags: FilterFlags = [:]) {
|
||||
fdescribe(description, closure, flags: flags)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus an `it` closure, focusing the example.
|
||||
If any examples in the test suite are focused, only those examples are executed.
|
||||
*/
|
||||
public func fit(description: String, closure: () -> (), flags: FilterFlags = [:], file: String = __FILE__, line: Int = __LINE__) {
|
||||
World.sharedWorld().fit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
Provides a hook for Quick to be configured before any examples are run.
|
||||
Within this scope, override the +[QuickConfiguration configure:] method
|
||||
to set properties on a configuration object to customize Quick behavior.
|
||||
For details, see the documentation for Configuraiton.swift.
|
||||
|
||||
@param name The name of the configuration class. Like any Objective-C
|
||||
class name, this must be unique to the current runtime
|
||||
environment.
|
||||
*/
|
||||
#define QuickConfigurationBegin(name) \
|
||||
@interface name : QuickConfiguration; @end \
|
||||
@implementation name \
|
||||
|
||||
|
||||
/**
|
||||
Marks the end of a Quick configuration.
|
||||
Make sure you put this after `QuickConfigurationBegin`.
|
||||
*/
|
||||
#define QuickConfigurationEnd \
|
||||
@end \
|
||||
|
||||
|
||||
/**
|
||||
Defines a new QuickSpec. Define examples and example groups within the space
|
||||
between this and `QuickSpecEnd`.
|
||||
|
||||
@param name The name of the spec class. Like any Objective-C class name, this
|
||||
must be unique to the current runtime environment.
|
||||
*/
|
||||
#define QuickSpecBegin(name) \
|
||||
@interface name : QuickSpec; @end \
|
||||
@implementation name \
|
||||
- (void)spec { \
|
||||
|
||||
|
||||
/**
|
||||
Marks the end of a QuickSpec. Make sure you put this after `QuickSpecBegin`.
|
||||
*/
|
||||
#define QuickSpecEnd \
|
||||
} \
|
||||
@end \
|
||||
|
||||
typedef NSDictionary *(^QCKDSLSharedExampleContext)(void);
|
||||
typedef void (^QCKDSLSharedExampleBlock)(QCKDSLSharedExampleContext);
|
||||
typedef void (^QCKDSLEmptyBlock)(void);
|
||||
|
||||
extern void qck_beforeSuite(QCKDSLEmptyBlock closure);
|
||||
extern void qck_afterSuite(QCKDSLEmptyBlock closure);
|
||||
extern void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure);
|
||||
extern void qck_describe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_context(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_beforeEach(QCKDSLEmptyBlock closure);
|
||||
extern void qck_afterEach(QCKDSLEmptyBlock closure);
|
||||
extern void qck_pending(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
extern void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure);
|
||||
|
||||
#ifndef QUICK_DISABLE_SHORT_SYNTAX
|
||||
/**
|
||||
Defines a closure to be run prior to any examples in the test suite.
|
||||
You may define an unlimited number of these closures, but there is no
|
||||
guarantee as to the order in which they're run.
|
||||
|
||||
If the test suite crashes before the first example is run, this closure
|
||||
will not be executed.
|
||||
|
||||
@param closure The closure to be run prior to any examples in the test suite.
|
||||
*/
|
||||
static inline void beforeSuite(QCKDSLEmptyBlock closure) {
|
||||
qck_beforeSuite(closure);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Defines a closure to be run after all of the examples in the test suite.
|
||||
You may define an unlimited number of these closures, but there is no
|
||||
guarantee as to the order in which they're run.
|
||||
|
||||
If the test suite crashes before all examples are run, this closure
|
||||
will not be executed.
|
||||
|
||||
@param closure The closure to be run after all of the examples in the test suite.
|
||||
*/
|
||||
static inline void afterSuite(QCKDSLEmptyBlock closure) {
|
||||
qck_afterSuite(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a group of shared examples. These examples can be re-used in several locations
|
||||
by using the `itBehavesLike` function.
|
||||
|
||||
@param name The name of the shared example group. This must be unique across all shared example
|
||||
groups defined in a test suite.
|
||||
@param closure A closure containing the examples. This behaves just like an example group defined
|
||||
using `describe` or `context`--the closure may contain any number of `beforeEach`
|
||||
and `afterEach` closures, as well as any number of examples (defined using `it`).
|
||||
*/
|
||||
static inline void sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) {
|
||||
qck_sharedExamples(name, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example group. Example groups are logical groupings of examples.
|
||||
Example groups can share setup and teardown code.
|
||||
|
||||
@param description An arbitrary string describing the example group.
|
||||
@param closure A closure that can contain other examples.
|
||||
*/
|
||||
static inline void describe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_describe(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example group. Equivalent to `describe`.
|
||||
*/
|
||||
static inline void context(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_context(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a closure to be run prior to each example in the current example
|
||||
group. This closure is not run for pending or otherwise disabled examples.
|
||||
An example group may contain an unlimited number of beforeEach. They'll be
|
||||
run in the order they're defined, but you shouldn't rely on that behavior.
|
||||
|
||||
@param closure The closure to be run prior to each example.
|
||||
*/
|
||||
static inline void beforeEach(QCKDSLEmptyBlock closure) {
|
||||
qck_beforeEach(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a closure to be run after each example in the current example
|
||||
group. This closure is not run for pending or otherwise disabled examples.
|
||||
An example group may contain an unlimited number of afterEach. They'll be
|
||||
run in the order they're defined, but you shouldn't rely on that behavior.
|
||||
|
||||
@param closure The closure to be run after each example.
|
||||
*/
|
||||
static inline void afterEach(QCKDSLEmptyBlock closure) {
|
||||
qck_afterEach(closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example or example group that should not be executed. Use `pending` to temporarily disable
|
||||
examples or groups that should not be run yet.
|
||||
|
||||
@param description An arbitrary string describing the example or example group.
|
||||
@param closure A closure that will not be evaluated.
|
||||
*/
|
||||
static inline void pending(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_pending(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark a `describe` block as pending.
|
||||
This disables all examples within the block.
|
||||
*/
|
||||
static inline void xdescribe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_xdescribe(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark a `context` block as pending.
|
||||
This disables all examples within the block.
|
||||
*/
|
||||
static inline void xcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_xcontext(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus a `describe` block, focusing the examples in the block.
|
||||
If any examples in the test suite are focused, only those examples are executed.
|
||||
This trumps any explicitly focused or unfocused examples within the block--they are all treated as focused.
|
||||
*/
|
||||
static inline void fdescribe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_fdescribe(description, closure);
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus a `context` block. Equivalent to `fdescribe`.
|
||||
*/
|
||||
static inline void fcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_fcontext(description, closure);
|
||||
}
|
||||
|
||||
#define it qck_it
|
||||
#define xit qck_xit
|
||||
#define fit qck_fit
|
||||
#define itBehavesLike qck_itBehavesLike
|
||||
#define xitBehavesLike qck_xitBehavesLike
|
||||
#define fitBehavesLike qck_fitBehavesLike
|
||||
#endif
|
||||
|
||||
#define qck_it qck_it_builder(@{}, @(__FILE__), __LINE__)
|
||||
#define qck_xit qck_it_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__)
|
||||
#define qck_fit qck_it_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__)
|
||||
#define qck_itBehavesLike qck_itBehavesLike_builder(@{}, @(__FILE__), __LINE__)
|
||||
#define qck_xitBehavesLike qck_itBehavesLike_builder(@{Filter.pending: @YES}, @(__FILE__), __LINE__)
|
||||
#define qck_fitBehavesLike qck_itBehavesLike_builder(@{Filter.focused: @YES}, @(__FILE__), __LINE__)
|
||||
|
||||
typedef void (^QCKItBlock)(NSString *description, QCKDSLEmptyBlock closure);
|
||||
typedef void (^QCKItBehavesLikeBlock)(NSString *description, QCKDSLSharedExampleContext context);
|
||||
|
||||
extern QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line);
|
||||
extern QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line);
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#import "QCKDSL.h"
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
void qck_beforeSuite(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] beforeSuite:closure];
|
||||
}
|
||||
|
||||
void qck_afterSuite(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] afterSuite:closure];
|
||||
}
|
||||
|
||||
void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) {
|
||||
[[World sharedWorld] sharedExamples:name closure:closure];
|
||||
}
|
||||
|
||||
void qck_describe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] describe:description closure:closure flags:@{}];
|
||||
}
|
||||
|
||||
void qck_context(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_describe(description, closure);
|
||||
}
|
||||
|
||||
void qck_beforeEach(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] beforeEach:closure];
|
||||
}
|
||||
|
||||
void qck_afterEach(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] afterEach:closure];
|
||||
}
|
||||
|
||||
QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) {
|
||||
return ^(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] itWithDescription:description
|
||||
flags:flags
|
||||
file:file
|
||||
line:line
|
||||
closure:closure];
|
||||
};
|
||||
}
|
||||
|
||||
QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) {
|
||||
return ^(NSString *name, QCKDSLSharedExampleContext context) {
|
||||
[[World sharedWorld] itBehavesLikeSharedExampleNamed:name
|
||||
sharedExampleContext:context
|
||||
flags:flags
|
||||
file:file
|
||||
line:line];
|
||||
};
|
||||
}
|
||||
|
||||
void qck_pending(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] pending:description closure:closure];
|
||||
}
|
||||
|
||||
void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] xdescribe:description closure:closure flags:@{}];
|
||||
}
|
||||
|
||||
void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_xdescribe(description, closure);
|
||||
}
|
||||
|
||||
void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] fdescribe:description closure:closure flags:@{}];
|
||||
}
|
||||
|
||||
void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_fdescribe(description, closure);
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
Adds methods to World to support top-level DSL functions (Swift) and
|
||||
macros (Objective-C). These functions map directly to the DSL that test
|
||||
writers use in their specs.
|
||||
*/
|
||||
extension World {
|
||||
public func beforeSuite(closure: BeforeSuiteClosure) {
|
||||
suiteHooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
public func afterSuite(closure: AfterSuiteClosure) {
|
||||
suiteHooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
public func sharedExamples(name: String, closure: SharedExampleClosure) {
|
||||
registerSharedExample(name, closure: closure)
|
||||
}
|
||||
|
||||
public func describe(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
var group = ExampleGroup(description: description, flags: flags)
|
||||
currentExampleGroup!.appendExampleGroup(group)
|
||||
currentExampleGroup = group
|
||||
closure()
|
||||
currentExampleGroup = group.parent
|
||||
}
|
||||
|
||||
public func context(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
self.describe(description, closure: closure, flags: flags)
|
||||
}
|
||||
|
||||
public func fdescribe(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.describe(description, closure: closure, flags: focusedFlags)
|
||||
}
|
||||
|
||||
public func xdescribe(description: String, closure: () -> (), flags: FilterFlags) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.describe(description, closure: closure, flags: pendingFlags)
|
||||
}
|
||||
|
||||
public func beforeEach(closure: BeforeExampleClosure) {
|
||||
currentExampleGroup!.hooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
public func beforeEach(#closure: BeforeExampleWithMetadataClosure) {
|
||||
currentExampleGroup!.hooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
public func afterEach(closure: AfterExampleClosure) {
|
||||
currentExampleGroup!.hooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
public func afterEach(#closure: AfterExampleWithMetadataClosure) {
|
||||
currentExampleGroup!.hooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
@objc(itWithDescription:flags:file:line:closure:)
|
||||
public func it(description: String, flags: FilterFlags, file: String, line: Int, closure: () -> ()) {
|
||||
let callsite = Callsite(file: file, line: line)
|
||||
let example = Example(description: description, callsite: callsite, flags: flags, closure)
|
||||
currentExampleGroup!.appendExample(example)
|
||||
}
|
||||
|
||||
@objc(fitWithDescription:flags:file:line:closure:)
|
||||
public func fit(description: String, flags: FilterFlags, file: String, line: Int, closure: () -> ()) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.it(description, flags: focusedFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(xitWithDescription:flags:file:line:closure:)
|
||||
public func xit(description: String, flags: FilterFlags, file: String, line: Int, closure: () -> ()) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.it(description, flags: pendingFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:)
|
||||
public func itBehavesLike(name: String, sharedExampleContext: SharedExampleContext, flags: FilterFlags, file: String, line: Int) {
|
||||
let callsite = Callsite(file: file, line: line)
|
||||
let closure = World.sharedWorld().sharedExample(name)
|
||||
|
||||
var group = ExampleGroup(description: name, flags: flags)
|
||||
currentExampleGroup!.appendExampleGroup(group)
|
||||
currentExampleGroup = group
|
||||
closure(sharedExampleContext)
|
||||
currentExampleGroup!.walkDownExamples { (example: Example) in
|
||||
example.isSharedExample = true
|
||||
example.callsite = callsite
|
||||
}
|
||||
|
||||
currentExampleGroup = group.parent
|
||||
}
|
||||
|
||||
public func pending(description: String, closure: () -> ()) {
|
||||
println("Pending: \(description)")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
private var numberOfExamplesRun = 0
|
||||
|
||||
/**
|
||||
Examples, defined with the `it` function, use assertions to
|
||||
demonstrate how code should behave. These are like "tests" in XCTest.
|
||||
*/
|
||||
@objc final public class Example: Equatable {
|
||||
/**
|
||||
A boolean indicating whether the example is a shared example;
|
||||
i.e.: whether it is an example defined with `itBehavesLike`.
|
||||
*/
|
||||
public var isSharedExample = false
|
||||
|
||||
/**
|
||||
The site at which the example is defined.
|
||||
This must be set correctly in order for Xcode to highlight
|
||||
the correct line in red when reporting a failure.
|
||||
*/
|
||||
public var callsite: Callsite
|
||||
|
||||
weak internal var group: ExampleGroup?
|
||||
|
||||
private let description: String
|
||||
private let closure: () -> ()
|
||||
private let flags: FilterFlags
|
||||
|
||||
internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: () -> ()) {
|
||||
self.description = description
|
||||
self.closure = closure
|
||||
self.callsite = callsite
|
||||
self.flags = flags
|
||||
}
|
||||
|
||||
/**
|
||||
The example name. A name is a concatenation of the name of
|
||||
the example group the example belongs to, followed by the
|
||||
description of the example itself.
|
||||
|
||||
The example name is used to generate a test method selector
|
||||
to be displayed in Xcode's test navigator.
|
||||
*/
|
||||
public var name: String {
|
||||
switch group!.name {
|
||||
case .Some(let groupName): return "\(groupName), \(description)"
|
||||
case .None: return description
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Executes the example closure, as well as all before and after
|
||||
closures defined in the its surrounding example groups.
|
||||
*/
|
||||
public func run() {
|
||||
let world = World.sharedWorld()
|
||||
|
||||
if numberOfExamplesRun == 0 {
|
||||
world.suiteHooks.executeBefores()
|
||||
}
|
||||
|
||||
let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun)
|
||||
world.currentExampleMetadata = exampleMetadata
|
||||
|
||||
world.exampleHooks.executeBefores(exampleMetadata)
|
||||
for before in group!.befores {
|
||||
before(exampleMetadata: exampleMetadata)
|
||||
}
|
||||
|
||||
closure()
|
||||
|
||||
for after in group!.afters {
|
||||
after(exampleMetadata: exampleMetadata)
|
||||
}
|
||||
world.exampleHooks.executeAfters(exampleMetadata)
|
||||
|
||||
++numberOfExamplesRun
|
||||
|
||||
if !world.isRunningAdditionalSuites && numberOfExamplesRun >= world.exampleCount {
|
||||
world.suiteHooks.executeAfters()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Evaluates the filter flags set on this example and on the example groups
|
||||
this example belongs to. Flags set on the example are trumped by flags on
|
||||
the example group it belongs to. Flags on inner example groups are trumped
|
||||
by flags on outer example groups.
|
||||
*/
|
||||
internal var filterFlags: FilterFlags {
|
||||
var aggregateFlags = flags
|
||||
for (key, value) in group!.filterFlags {
|
||||
aggregateFlags[key] = value
|
||||
}
|
||||
return aggregateFlags
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a boolean indicating whether two Example objects are equal.
|
||||
If two examples are defined at the exact same callsite, they must be equal.
|
||||
*/
|
||||
public func ==(lhs: Example, rhs: Example) -> Bool {
|
||||
return lhs.callsite == rhs.callsite
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
Example groups are logical groupings of examples, defined with
|
||||
the `describe` and `context` functions. Example groups can share
|
||||
setup and teardown code.
|
||||
*/
|
||||
@objc final public class ExampleGroup {
|
||||
weak internal var parent: ExampleGroup?
|
||||
internal let hooks = ExampleHooks()
|
||||
|
||||
private let description: String
|
||||
private let flags: FilterFlags
|
||||
private let isInternalRootExampleGroup: Bool
|
||||
private var childGroups = [ExampleGroup]()
|
||||
private var childExamples = [Example]()
|
||||
|
||||
internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) {
|
||||
self.description = description
|
||||
self.flags = flags
|
||||
self.isInternalRootExampleGroup = isInternalRootExampleGroup
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of examples that belong to this example group,
|
||||
or to any of its descendant example groups.
|
||||
*/
|
||||
public var examples: [Example] {
|
||||
var examples = childExamples
|
||||
for group in childGroups {
|
||||
examples.extend(group.examples)
|
||||
}
|
||||
return examples
|
||||
}
|
||||
|
||||
internal var name: String? {
|
||||
if let parent = parent {
|
||||
switch(parent.name) {
|
||||
case .Some(let name): return "\(name), \(description)"
|
||||
case .None: return description
|
||||
}
|
||||
} else {
|
||||
return isInternalRootExampleGroup ? nil : description
|
||||
}
|
||||
}
|
||||
|
||||
internal var filterFlags: FilterFlags {
|
||||
var aggregateFlags = flags
|
||||
walkUp() { (group: ExampleGroup) -> () in
|
||||
for (key, value) in group.flags {
|
||||
aggregateFlags[key] = value
|
||||
}
|
||||
}
|
||||
return aggregateFlags
|
||||
}
|
||||
|
||||
internal var befores: [BeforeExampleWithMetadataClosure] {
|
||||
var closures = hooks.befores.reverse()
|
||||
walkUp() { (group: ExampleGroup) -> () in
|
||||
closures.extend(group.hooks.befores.reverse())
|
||||
}
|
||||
return closures.reverse()
|
||||
}
|
||||
|
||||
internal var afters: [AfterExampleWithMetadataClosure] {
|
||||
var closures = hooks.afters
|
||||
walkUp() { (group: ExampleGroup) -> () in
|
||||
closures.extend(group.hooks.afters)
|
||||
}
|
||||
return closures
|
||||
}
|
||||
|
||||
internal func walkDownExamples(callback: (example: Example) -> ()) {
|
||||
for example in childExamples {
|
||||
callback(example: example)
|
||||
}
|
||||
for group in childGroups {
|
||||
group.walkDownExamples(callback)
|
||||
}
|
||||
}
|
||||
|
||||
internal func appendExampleGroup(group: ExampleGroup) {
|
||||
group.parent = self
|
||||
childGroups.append(group)
|
||||
}
|
||||
|
||||
internal func appendExample(example: Example) {
|
||||
example.group = self
|
||||
childExamples.append(example)
|
||||
}
|
||||
|
||||
private func walkUp(callback: (group: ExampleGroup) -> ()) {
|
||||
var group = self
|
||||
while let parent = group.parent {
|
||||
callback(group: parent)
|
||||
group = parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
A class that encapsulates information about an example,
|
||||
including the index at which the example was executed, as
|
||||
well as the example itself.
|
||||
*/
|
||||
@objc final public class ExampleMetadata {
|
||||
/**
|
||||
The example for which this metadata was collected.
|
||||
*/
|
||||
public let example: Example
|
||||
|
||||
/**
|
||||
The index at which this example was executed in the
|
||||
test suite.
|
||||
*/
|
||||
public let exampleIndex: Int
|
||||
|
||||
internal init(example: Example, exampleIndex: Int) {
|
||||
self.example = example
|
||||
self.exampleIndex = exampleIndex
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import Foundation
|
||||
|
||||
@objc final class Failure {
|
||||
let callsite: Callsite
|
||||
let exception: NSException
|
||||
|
||||
init(exception: NSException, callsite: Callsite) {
|
||||
self.exception = exception
|
||||
self.callsite = callsite
|
||||
}
|
||||
|
||||
@objc(failureWithException:callsite:)
|
||||
class func failure(exception: NSException, callsite: Callsite) -> Failure {
|
||||
return Failure(exception: exception, callsite: callsite)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
A mapping of string keys to booleans that can be used to
|
||||
filter examples or example groups. For example, a "focused"
|
||||
example would have the flags [Focused: true].
|
||||
*/
|
||||
public typealias FilterFlags = [String: Bool]
|
||||
|
||||
/**
|
||||
A namespace for filter flag keys, defined primarily to make the
|
||||
keys available in Objective-C.
|
||||
*/
|
||||
@objc(QCKFilter) final public class Filter {
|
||||
/**
|
||||
Example and example groups with [Focused: true] are included in test runs,
|
||||
excluding all other examples without this flag. Use this to only run one or
|
||||
two tests that you're currently focusing on.
|
||||
*/
|
||||
public class var focused: String {
|
||||
return "focused"
|
||||
}
|
||||
|
||||
/**
|
||||
Example and example groups with [Pending: true] are excluded from test runs.
|
||||
Use this to temporarily suspend examples that you know do not pass yet.
|
||||
*/
|
||||
public class var pending: String {
|
||||
return "pending"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// MARK: Example Hooks
|
||||
|
||||
/**
|
||||
A closure executed before an example is run.
|
||||
*/
|
||||
public typealias BeforeExampleClosure = () -> ()
|
||||
|
||||
/**
|
||||
A closure executed before an example is run. The closure is given example metadata,
|
||||
which contains information about the example that is about to be run.
|
||||
*/
|
||||
public typealias BeforeExampleWithMetadataClosure = (exampleMetadata: ExampleMetadata) -> ()
|
||||
|
||||
/**
|
||||
A closure executed after an example is run.
|
||||
*/
|
||||
public typealias AfterExampleClosure = BeforeExampleClosure
|
||||
|
||||
/**
|
||||
A closure executed after an example is run. The closure is given example metadata,
|
||||
which contains information about the example that has just finished running.
|
||||
*/
|
||||
public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure
|
||||
|
||||
// MARK: Suite Hooks
|
||||
|
||||
/**
|
||||
A closure executed before any examples are run.
|
||||
*/
|
||||
public typealias BeforeSuiteClosure = () -> ()
|
||||
|
||||
/**
|
||||
A closure executed after all examples have finished running.
|
||||
*/
|
||||
public typealias AfterSuiteClosure = BeforeSuiteClosure
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
A container for closures to be executed before and after each example.
|
||||
*/
|
||||
final internal class ExampleHooks {
|
||||
|
||||
internal var befores: [BeforeExampleWithMetadataClosure] = []
|
||||
internal var afters: [AfterExampleWithMetadataClosure] = []
|
||||
|
||||
internal func appendBefore(closure: BeforeExampleWithMetadataClosure) {
|
||||
befores.append(closure)
|
||||
}
|
||||
|
||||
internal func appendBefore(closure: BeforeExampleClosure) {
|
||||
befores.append { (exampleMetadata: ExampleMetadata) in closure() }
|
||||
}
|
||||
|
||||
internal func appendAfter(closure: AfterExampleWithMetadataClosure) {
|
||||
afters.append(closure)
|
||||
}
|
||||
|
||||
internal func appendAfter(closure: AfterExampleClosure) {
|
||||
afters.append { (exampleMetadata: ExampleMetadata) in closure() }
|
||||
}
|
||||
|
||||
internal func executeBefores(exampleMetadata: ExampleMetadata) {
|
||||
for before in befores {
|
||||
before(exampleMetadata: exampleMetadata)
|
||||
}
|
||||
}
|
||||
|
||||
internal func executeAfters(exampleMetadata: ExampleMetadata) {
|
||||
for after in afters {
|
||||
after(exampleMetadata: exampleMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
A container for closures to be executed before and after all examples.
|
||||
*/
|
||||
final internal class SuiteHooks {
|
||||
internal var befores: [BeforeSuiteClosure] = []
|
||||
internal var beforesAlreadyExecuted = false
|
||||
|
||||
internal var afters: [AfterSuiteClosure] = []
|
||||
internal var aftersAlreadyExecuted = false
|
||||
|
||||
internal func appendBefore(closure: BeforeSuiteClosure) {
|
||||
befores.append(closure)
|
||||
}
|
||||
|
||||
internal func appendAfter(closure: AfterSuiteClosure) {
|
||||
afters.append(closure)
|
||||
}
|
||||
|
||||
internal func executeBefores() {
|
||||
assert(!beforesAlreadyExecuted)
|
||||
for before in befores {
|
||||
before()
|
||||
}
|
||||
beforesAlreadyExecuted = true
|
||||
}
|
||||
|
||||
internal func executeAfters() {
|
||||
assert(!aftersAlreadyExecuted)
|
||||
for after in afters {
|
||||
after()
|
||||
}
|
||||
aftersAlreadyExecuted = true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
QuickSpec converts example names into test methods.
|
||||
Those test methods need valid selector names, which means no whitespace,
|
||||
control characters, etc. This category gives NSString objects an easy way
|
||||
to replace those illegal characters with underscores.
|
||||
*/
|
||||
@interface NSString (QCKSelectorName)
|
||||
|
||||
/**
|
||||
Returns a string with underscores in place of all characters that cannot
|
||||
be included in a selector (SEL) name.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSString *qck_selectorName;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#import "NSString+QCKSelectorName.h"
|
||||
|
||||
@implementation NSString (QCKSelectorName)
|
||||
|
||||
- (NSString *)qck_selectorName {
|
||||
static NSMutableCharacterSet *invalidCharacters = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
invalidCharacters = [NSMutableCharacterSet new];
|
||||
|
||||
NSCharacterSet *whitespaceCharacterSet = [NSCharacterSet whitespaceCharacterSet];
|
||||
NSCharacterSet *newlineCharacterSet = [NSCharacterSet newlineCharacterSet];
|
||||
NSCharacterSet *illegalCharacterSet = [NSCharacterSet illegalCharacterSet];
|
||||
NSCharacterSet *controlCharacterSet = [NSCharacterSet controlCharacterSet];
|
||||
NSCharacterSet *punctuationCharacterSet = [NSCharacterSet punctuationCharacterSet];
|
||||
NSCharacterSet *nonBaseCharacterSet = [NSCharacterSet nonBaseCharacterSet];
|
||||
NSCharacterSet *symbolCharacterSet = [NSCharacterSet symbolCharacterSet];
|
||||
|
||||
[invalidCharacters formUnionWithCharacterSet:whitespaceCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:newlineCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:illegalCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:controlCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:punctuationCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:nonBaseCharacterSet];
|
||||
[invalidCharacters formUnionWithCharacterSet:symbolCharacterSet];
|
||||
});
|
||||
|
||||
NSArray *validComponents = [self componentsSeparatedByCharactersInSet:invalidCharacters];
|
||||
|
||||
return [validComponents componentsJoinedByString:@"_"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for Quick.
|
||||
FOUNDATION_EXPORT double QuickVersionNumber;
|
||||
|
||||
//! Project version string for Quick.
|
||||
FOUNDATION_EXPORT const unsigned char QuickVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <Quick/PublicHeader.h>
|
||||
|
||||
#import <Quick/QuickSpec.h>
|
||||
#import <Quick/QCKDSL.h>
|
||||
#import <Quick/QuickConfiguration.h>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#import <XCTest/XCTest.h>
|
||||
|
||||
/**
|
||||
QuickSpec is a base class all specs written in Quick inherit from.
|
||||
They need to inherit from QuickSpec, a subclass of XCTestCase, in
|
||||
order to be discovered by the XCTest framework.
|
||||
|
||||
XCTest automatically compiles a list of XCTestCase subclasses included
|
||||
in the test target. It iterates over each class in that list, and creates
|
||||
a new instance of that class for each test method. It then creates an
|
||||
"invocation" to execute that test method. The invocation is an instance of
|
||||
NSInvocation, which represents a single message send in Objective-C.
|
||||
The invocation is set on the XCTestCase instance, and the test is run.
|
||||
|
||||
Most of the code in QuickSpec is dedicated to hooking into XCTest events.
|
||||
First, when the spec is first loaded and before it is sent any messages,
|
||||
the +[NSObject initialize] method is called. QuickSpec overrides this method
|
||||
to call +[QuickSpec spec]. This builds the example group stacks and
|
||||
registers them with Quick.World, a global register of examples.
|
||||
|
||||
Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest
|
||||
automatically finds all methods whose selectors begin with the string "test".
|
||||
However, QuickSpec overrides this default behavior by implementing the
|
||||
+[XCTestCase testInvocations] method. This method iterates over each example
|
||||
registered in Quick.World, defines a new method for that example, and
|
||||
returns an invocation to call that method to XCTest. Those invocations are
|
||||
the tests that are run by XCTest. Their selector names are displayed in
|
||||
the Xcode test navigation bar.
|
||||
*/
|
||||
@interface QuickSpec : XCTestCase
|
||||
|
||||
/**
|
||||
Override this method in your spec to define a set of example groups
|
||||
and examples.
|
||||
|
||||
override class func spec() {
|
||||
describe("winter") {
|
||||
it("is coming") {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
See DSL.swift for more information on what syntax is available.
|
||||
*/
|
||||
- (void)spec;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
#import "QuickSpec.h"
|
||||
#import "QuickConfiguration.h"
|
||||
#import "NSString+QCKSelectorName.h"
|
||||
#import <Quick/Quick-Swift.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
const void * const QCKExampleKey = &QCKExampleKey;
|
||||
|
||||
@interface QuickSpec ()
|
||||
@property (nonatomic, strong) Example *example;
|
||||
@end
|
||||
|
||||
@implementation QuickSpec
|
||||
|
||||
#pragma mark - XCTestCase Overrides
|
||||
|
||||
/**
|
||||
The runtime sends initialize to each class in a program just before the class, or any class
|
||||
that inherits from it, is sent its first message from within the program. QuickSpec hooks into
|
||||
this event to compile the example groups for this spec subclass.
|
||||
|
||||
If an exception occurs when compiling the examples, report it to the user. Chances are they
|
||||
included an expectation outside of a "it", "describe", or "context" block.
|
||||
*/
|
||||
+ (void)initialize {
|
||||
[QuickConfiguration initialize];
|
||||
|
||||
World *world = [World sharedWorld];
|
||||
world.currentExampleGroup = [world rootExampleGroupForSpecClass:[self class]];
|
||||
QuickSpec *spec = [self new];
|
||||
|
||||
@try {
|
||||
[spec spec];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"An exception occurred when building Quick's example groups.\n"
|
||||
@"Some possible reasons this might happen include:\n\n"
|
||||
@"- An 'expect(...).to' expectation was evaluated outside of "
|
||||
@"an 'it', 'context', or 'describe' block\n"
|
||||
@"- 'sharedExamples' was called twice with the same name\n"
|
||||
@"- 'itBehavesLike' was called with a name that is not registered as a shared example\n\n"
|
||||
@"Here's the original exception: '%@', reason: '%@', userInfo: '%@'",
|
||||
exception.name, exception.reason, exception.userInfo];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Invocations for each test method in the test case. QuickSpec overrides this method to define a
|
||||
new method for each example defined in +[QuickSpec spec].
|
||||
|
||||
@return An array of invocations that execute the newly defined example methods.
|
||||
*/
|
||||
+ (NSArray *)testInvocations {
|
||||
NSArray *examples = [[World sharedWorld] examplesForSpecClass:[self class]];
|
||||
NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:[examples count]];
|
||||
for (Example *example in examples) {
|
||||
SEL selector = [self addInstanceMethodForExample:example];
|
||||
NSInvocation *invocation = [self invocationForInstanceMethodWithSelector:selector
|
||||
example:example];
|
||||
[invocations addObject:invocation];
|
||||
}
|
||||
|
||||
return invocations;
|
||||
}
|
||||
|
||||
/**
|
||||
XCTest sets the invocation for the current test case instance using this setter.
|
||||
QuickSpec hooks into this event to give the test case a reference to the current example.
|
||||
It will need this reference to correctly report its name to XCTest.
|
||||
*/
|
||||
- (void)setInvocation:(NSInvocation *)invocation {
|
||||
self.example = objc_getAssociatedObject(invocation, QCKExampleKey);
|
||||
[super setInvocation:invocation];
|
||||
}
|
||||
|
||||
#pragma mark - Public Interface
|
||||
|
||||
- (void)spec { }
|
||||
|
||||
#pragma mark - Internal Methods
|
||||
|
||||
/**
|
||||
QuickSpec uses this method to dynamically define a new instance method for the
|
||||
given example. The instance method runs the example, catching any exceptions.
|
||||
The exceptions are then reported as test failures.
|
||||
|
||||
In order to report the correct file and line number, examples must raise exceptions
|
||||
containing following keys in their userInfo:
|
||||
|
||||
- "SenTestFilenameKey": A String representing the file name
|
||||
- "SenTestLineNumberKey": An Int representing the line number
|
||||
|
||||
These keys used to be used by SenTestingKit, and are still used by some testing tools
|
||||
in the wild. See: https://github.com/Quick/Quick/pull/41
|
||||
|
||||
@return The selector of the newly defined instance method.
|
||||
*/
|
||||
+ (SEL)addInstanceMethodForExample:(Example *)example {
|
||||
IMP implementation = imp_implementationWithBlock(^(id self){
|
||||
[example run];
|
||||
});
|
||||
const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(id), @encode(id), @encode(SEL)] UTF8String];
|
||||
SEL selector = NSSelectorFromString(example.name.qck_selectorName);
|
||||
class_addMethod(self, selector, implementation, types);
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
+ (NSInvocation *)invocationForInstanceMethodWithSelector:(SEL)selector
|
||||
example:(Example *)example {
|
||||
NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
invocation.selector = selector;
|
||||
objc_setAssociatedObject(invocation,
|
||||
QCKExampleKey,
|
||||
example,
|
||||
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
return invocation;
|
||||
}
|
||||
|
||||
/**
|
||||
This method is used to record failures, whether they represent example
|
||||
expectations that were not met, or exceptions raised during test setup
|
||||
and teardown. By default, the failure will be reported as an
|
||||
XCTest failure, and the example will be highlighted in Xcode.
|
||||
*/
|
||||
- (void)recordFailureWithDescription:(NSString *)description
|
||||
inFile:(NSString *)filePath
|
||||
atLine:(NSUInteger)lineNumber
|
||||
expected:(BOOL)expected {
|
||||
if (self.example.isSharedExample) {
|
||||
filePath = self.example.callsite.file;
|
||||
lineNumber = self.example.callsite.line;
|
||||
}
|
||||
[super recordFailureWithDescription:description
|
||||
inFile:filePath
|
||||
atLine:lineNumber
|
||||
expected:expected];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
import Foundation
|
||||
|
||||
/**
|
||||
A closure that, when evaluated, returns a dictionary of key-value
|
||||
pairs that can be accessed from within a group of shared examples.
|
||||
*/
|
||||
public typealias SharedExampleContext = () -> (NSDictionary)
|
||||
|
||||
/**
|
||||
A closure that is used to define a group of shared examples. This
|
||||
closure may contain any number of example and example groups.
|
||||
*/
|
||||
public typealias SharedExampleClosure = (SharedExampleContext) -> ()
|
||||
|
||||
/**
|
||||
A collection of state Quick builds up in order to work its magic.
|
||||
World is primarily responsible for maintaining a mapping of QuickSpec
|
||||
classes to root example groups for those classes.
|
||||
|
||||
It also maintains a mapping of shared example names to shared
|
||||
example closures.
|
||||
|
||||
You may configure how Quick behaves by calling the -[World configure:]
|
||||
method from within an overridden +[QuickConfiguration configure:] method.
|
||||
*/
|
||||
@objc final public class World {
|
||||
/**
|
||||
The example group that is currently being run.
|
||||
The DSL requires that this group is correctly set in order to build a
|
||||
correct hierarchy of example groups and their examples.
|
||||
*/
|
||||
public var currentExampleGroup: ExampleGroup?
|
||||
|
||||
/**
|
||||
The example metadata of the test that is currently being run.
|
||||
This is useful for using the Quick test metadata (like its name) at
|
||||
runtime.
|
||||
*/
|
||||
|
||||
public var currentExampleMetadata: ExampleMetadata?
|
||||
|
||||
/**
|
||||
A flag that indicates whether additional test suites are being run
|
||||
within this test suite. This is only true within the context of Quick
|
||||
functional tests.
|
||||
*/
|
||||
public var isRunningAdditionalSuites = false
|
||||
|
||||
private var specs: Dictionary<String, ExampleGroup> = [:]
|
||||
private var sharedExamples: [String: SharedExampleClosure] = [:]
|
||||
private let configuration = Configuration()
|
||||
private var isConfigurationFinalized = false
|
||||
|
||||
internal var exampleHooks: ExampleHooks {return configuration.exampleHooks }
|
||||
internal var suiteHooks: SuiteHooks { return configuration.suiteHooks }
|
||||
|
||||
// MARK: Singleton Constructor
|
||||
|
||||
private init() {}
|
||||
private struct Shared {
|
||||
static let instance = World()
|
||||
}
|
||||
public class func sharedWorld() -> World {
|
||||
return Shared.instance
|
||||
}
|
||||
|
||||
// MARK: Public Interface
|
||||
|
||||
/**
|
||||
Exposes the World's Configuration object within the scope of the closure
|
||||
so that it may be configured. This method must not be called outside of
|
||||
an overridden +[QuickConfiguration configure:] method.
|
||||
|
||||
:param: closure A closure that takes a Configuration object that can
|
||||
be mutated to change Quick's behavior.
|
||||
*/
|
||||
public func configure(closure: QuickConfigurer) {
|
||||
assert(!isConfigurationFinalized,
|
||||
"Quick cannot be configured outside of a +[QuickConfiguration configure:] method. You should not call -[World configure:] directly. Instead, subclass QuickConfiguration and override the +[QuickConfiguration configure:] method.")
|
||||
closure(configuration: configuration)
|
||||
}
|
||||
|
||||
/**
|
||||
Finalizes the World's configuration.
|
||||
Any subsequent calls to World.configure() will raise.
|
||||
*/
|
||||
public func finalizeConfiguration() {
|
||||
isConfigurationFinalized = true
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an internally constructed root example group for the given
|
||||
QuickSpec class.
|
||||
|
||||
A root example group with the description "root example group" is lazily
|
||||
initialized for each QuickSpec class. This root example group wraps the
|
||||
top level of a -[QuickSpec spec] method--it's thanks to this group that
|
||||
users can define beforeEach and it closures at the top level, like so:
|
||||
|
||||
override func spec() {
|
||||
// These belong to the root example group
|
||||
beforeEach {}
|
||||
it("is at the top level") {}
|
||||
}
|
||||
|
||||
:param: cls The QuickSpec class for which to retrieve the root example group.
|
||||
:returns: The root example group for the class.
|
||||
*/
|
||||
public func rootExampleGroupForSpecClass(cls: AnyClass) -> ExampleGroup {
|
||||
let name = NSStringFromClass(cls)
|
||||
if let group = specs[name] {
|
||||
return group
|
||||
} else {
|
||||
let group = ExampleGroup(
|
||||
description: "root example group",
|
||||
flags: [:],
|
||||
isInternalRootExampleGroup: true
|
||||
)
|
||||
specs[name] = group
|
||||
return group
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all examples that should be run for a given spec class.
|
||||
There are two filtering passes that occur when determining which examples should be run.
|
||||
That is, these examples are the ones that are included by inclusion filters, and are
|
||||
not excluded by exclusion filters.
|
||||
|
||||
:param: specClass The QuickSpec subclass for which examples are to be returned.
|
||||
:returns: A list of examples to be run as test invocations.
|
||||
*/
|
||||
@objc(examplesForSpecClass:)
|
||||
public func examples(specClass: AnyClass) -> [Example] {
|
||||
// 1. Grab all included examples.
|
||||
let included = includedExamples
|
||||
// 2. Grab the intersection of (a) examples for this spec, and (b) included examples.
|
||||
let spec = rootExampleGroupForSpecClass(specClass).examples.filter { contains(included, $0) }
|
||||
// 3. Remove all excluded examples.
|
||||
return spec.filter { example in
|
||||
!self.configuration.exclusionFilters.reduce(false) { $0 || $1(example: example) }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal func registerSharedExample(name: String, closure: SharedExampleClosure) {
|
||||
raiseIfSharedExampleAlreadyRegistered(name)
|
||||
sharedExamples[name] = closure
|
||||
}
|
||||
|
||||
internal func sharedExample(name: String) -> SharedExampleClosure {
|
||||
raiseIfSharedExampleNotRegistered(name)
|
||||
return sharedExamples[name]!
|
||||
}
|
||||
|
||||
internal var exampleCount: Int {
|
||||
return allExamples.count
|
||||
}
|
||||
|
||||
private var allExamples: [Example] {
|
||||
var all: [Example] = []
|
||||
for (_, group) in specs {
|
||||
group.walkDownExamples { all.append($0) }
|
||||
}
|
||||
return all
|
||||
}
|
||||
|
||||
private var includedExamples: [Example] {
|
||||
let all = allExamples
|
||||
let included = all.filter { example in
|
||||
return self.configuration.inclusionFilters.reduce(false) { $0 || $1(example: example) }
|
||||
}
|
||||
|
||||
if included.isEmpty && configuration.runAllWhenEverythingFiltered {
|
||||
return all
|
||||
} else {
|
||||
return included
|
||||
}
|
||||
}
|
||||
|
||||
private func raiseIfSharedExampleAlreadyRegistered(name: String) {
|
||||
if sharedExamples[name] != nil {
|
||||
NSException(name: NSInternalInconsistencyException,
|
||||
reason: "A shared example named '\(name)' has already been registered.",
|
||||
userInfo: nil).raise()
|
||||
}
|
||||
}
|
||||
|
||||
private func raiseIfSharedExampleNotRegistered(name: String) {
|
||||
if sharedExamples[name] == nil {
|
||||
NSException(name: NSInternalInconsistencyException,
|
||||
reason: "No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(sharedExamples.keys))'",
|
||||
userInfo: nil).raise()
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.3.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${CURRENT_PROJECT_VERSION}</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
10
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-Private.xcconfig
generated
Normal file
10
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-Private.xcconfig
generated
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include "Pods-cameraTests-Nimble.xcconfig"
|
||||
CONFIGURATION_BUILD_DIR = $PODS_FRAMEWORK_BUILD_PATH
|
||||
FRAMEWORK_SEARCH_PATHS = "$PODS_FRAMEWORK_BUILD_PATH" ${PODS_CAMERATESTS_NIMBLE_FRAMEWORK_SEARCH_PATHS}
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Nimble" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Nimble" "${PODS_ROOT}/Headers/Public/Quick"
|
||||
OTHER_LDFLAGS = ${PODS_CAMERATESTS_NIMBLE_OTHER_LDFLAGS} -ObjC
|
||||
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
|
||||
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-cameraTests
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
SKIP_INSTALL = YES
|
||||
5
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-dummy.m
generated
Normal file
5
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-dummy.m
generated
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_Pods_cameraTests_Nimble : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_Pods_cameraTests_Nimble
|
||||
@end
|
||||
5
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-prefix.pch
generated
Normal file
5
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-prefix.pch
generated
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
#import "Pods-cameraTests-environment.h"
|
||||
9
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-umbrella.h
generated
Normal file
9
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble-umbrella.h
generated
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "Nimble.h"
|
||||
#import "DSL.h"
|
||||
#import "NMBExceptionCapture.h"
|
||||
|
||||
FOUNDATION_EXPORT double NimbleVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char NimbleVersionString[];
|
||||
|
||||
6
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.modulemap
generated
Normal file
6
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.modulemap
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
framework module Nimble {
|
||||
umbrella header "Pods-cameraTests-Nimble-umbrella.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
2
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.xcconfig
generated
Normal file
2
Pods/Target Support Files/Pods-cameraTests-Nimble/Pods-cameraTests-Nimble.xcconfig
generated
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
PODS_CAMERATESTS_NIMBLE_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(SDKROOT)/Developer/Library/Frameworks" "$(PLATFORM_DIR)/Developer/Library/Frameworks"
|
||||
PODS_CAMERATESTS_NIMBLE_OTHER_LDFLAGS = -framework "XCTest"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue