Removed quick.

This commit is contained in:
Natalia Terlecka 2015-05-12 10:17:17 +01:00
parent 296be1bdb3
commit c579d2b87b
86 changed files with 963 additions and 4535 deletions

View File

@ -4,6 +4,7 @@ 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'
pod 'Nimble'
end

View File

@ -1,29 +1,10 @@
PODS:
- Nimble (0.3.0)
- Quick (0.2.2)
- Nimble (0.4.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
- Nimble
SPEC CHECKSUMS:
Nimble: 55fef248ef3703024ce431db817160ad24d89ba3
Quick: 1bda8b4c8d43f6b4dd69ca001918b1767b3c9c93
Nimble: 49b7a7da8919f42823d37c6d68cc6d15a7009f32
COCOAPODS: 0.36.0
COCOAPODS: 0.37.1

View File

@ -1 +0,0 @@
../../../Quick/Quick/NSString+QCKSelectorName.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/DSL/QCKDSL.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/Quick.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/Configuration/QuickConfiguration.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/QuickSpec.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/NSString+QCKSelectorName.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/DSL/QCKDSL.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/Quick.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/Configuration/QuickConfiguration.h

View File

@ -1 +0,0 @@
../../../Quick/Quick/QuickSpec.h

View File

@ -1,26 +0,0 @@
{
"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
}

27
Pods/Manifest.lock generated
View File

@ -1,29 +1,10 @@
PODS:
- Nimble (0.3.0)
- Quick (0.2.2)
- Nimble (0.4.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
- Nimble
SPEC CHECKSUMS:
Nimble: 55fef248ef3703024ce431db817160ad24d89ba3
Quick: 1bda8b4c8d43f6b4dd69ca001918b1767b3c9c93
Nimble: 49b7a7da8919f42823d37c6d68cc6d15a7009f32
COCOAPODS: 0.36.0
COCOAPODS: 0.37.1

View File

@ -9,5 +9,4 @@ public protocol AssertionHandler {
/// Defaults to a private test handler that passes through to XCTest.
///
/// @see AssertionHandler
var CurrentAssertionHandler: AssertionHandler = XCTestHandler()
public var NimbleAssertionHandler: AssertionHandler = NimbleXCTestHandler()

View File

@ -40,11 +40,11 @@ public class AssertionRecorder : AssertionHandler {
///
/// @see AssertionHandler
public func withAssertionHandler(tempAssertionHandler: AssertionHandler, closure: () -> Void) {
let oldRecorder = CurrentAssertionHandler
let oldRecorder = NimbleAssertionHandler
let capturer = NMBExceptionCapture(handler: nil, finally: ({
CurrentAssertionHandler = oldRecorder
NimbleAssertionHandler = oldRecorder
}))
CurrentAssertionHandler = tempAssertionHandler
NimbleAssertionHandler = tempAssertionHandler
capturer.tryBlock {
closure()
}

View File

@ -0,0 +1,12 @@
import Foundation
import XCTest
/// Default handler for Nimble. This assertion handler passes failures along to
/// XCTest.
public class NimbleXCTestHandler : AssertionHandler {
public func assert(assertion: Bool, message: String, location: SourceLocation) {
if !assertion {
XCTFail(message, file: location.file, line: location.line)
}
}
}

View File

@ -1,10 +0,0 @@
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)
}
}
}

View File

@ -4,7 +4,7 @@ import Foundation
/// 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 {
public class func until(#timeout: NSTimeInterval, file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
var completed = false
var token: dispatch_once_t = 0
let result = pollBlock(pollInterval: 0.01, timeoutInterval: timeout) {
@ -23,21 +23,21 @@ import Foundation
}
}
public class func until(action: (() -> Void) -> Void, file: String = __FILE__, line: UInt = __LINE__) -> Void {
until(timeout: 1, action: action, file: file, line: line)
public class func until(file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
until(timeout: 1, file: file, line: line, action: action)
}
}
/// 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)
public func waitUntil(#timeout: NSTimeInterval, file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
NMBWait.until(timeout: timeout, file: file, line: line, action: action)
}
/// 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)
public func waitUntil(file: String = __FILE__, line: UInt = __LINE__, action: (() -> Void) -> Void) -> Void {
NMBWait.until(file: file, line: line, action: action)
}

View File

@ -1,9 +1,10 @@
/// 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> {
public func expect<T>(@autoclosure(escaping) expression: () -> T?, file: String = __FILE__, line: UInt = __LINE__) -> Expectation<T> {
return Expectation(
expression: Expression(
expression: expression,
location: SourceLocation(file: file, line: line)))
location: SourceLocation(file: file, line: line),
isClosure: true))
}
/// Make an expectation on a given actual value. The closure is lazily invoked.
@ -11,12 +12,13 @@ public func expect<T>(file: String = __FILE__, line: UInt = __LINE__, expression
return Expectation(
expression: Expression(
expression: expression,
location: SourceLocation(file: file, line: line)))
location: SourceLocation(file: file, line: line),
isClosure: true))
}
/// 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)
NimbleAssertionHandler.assert(false, message: message, location: location)
}
/// Always fails the test with a message.

View File

@ -4,7 +4,7 @@ public struct Expectation<T> {
let expression: Expression<T>
public func verify(pass: Bool, _ message: String) {
CurrentAssertionHandler.assert(pass, message: message, location: expression.location)
NimbleAssertionHandler.assert(pass, message: message, location: expression.location)
}
public func to<U where U: Matcher, U.ValueType == T>(matcher: U) {

View File

@ -16,21 +16,24 @@ public struct Expression<T> {
internal let _expression: (Bool) -> T?
internal let _withoutCaching: Bool
public let location: SourceLocation
public let isClosure: Bool
public init(expression: () -> T?, location: SourceLocation) {
public init(expression: () -> T?, location: SourceLocation, isClosure: Bool = false) {
self._expression = memoizedClosure(expression)
self.location = location
self._withoutCaching = false
self.isClosure = isClosure
}
public init(memoizedExpression: (Bool) -> T?, location: SourceLocation, withoutCaching: Bool) {
public init(memoizedExpression: (Bool) -> T?, location: SourceLocation, withoutCaching: Bool, isClosure: Bool = false) {
self._expression = memoizedExpression
self.location = location
self._withoutCaching = withoutCaching
self.isClosure = isClosure
}
public func cast<U>(block: (T?) -> U?) -> Expression<U> {
return Expression<U>(expression: ({ block(self.evaluate()) }), location: self.location)
return Expression<U>(expression: ({ block(self.evaluate()) }), location: self.location, isClosure: self.isClosure)
}
public func evaluate() -> T? {
@ -38,6 +41,6 @@ public struct Expression<T> {
}
public func withoutCaching() -> Expression<T> {
return Expression(memoizedExpression: self._expression, location: location, withoutCaching: true)
return Expression(memoizedExpression: self._expression, location: location, withoutCaching: true, isClosure: isClosure)
}
}

View File

@ -16,7 +16,7 @@ public class FailureMessage {
if let actualValue = actualValue {
value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)"
}
var lines: [String] = (value as NSString).componentsSeparatedByString("\n") as [String]
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)

View File

@ -0,0 +1,99 @@
import Foundation
public func allPass<T,U where U: SequenceType, U.Generator.Element == T>
(passFunc: (T?) -> Bool) -> NonNilMatcherFunc<U> {
return allPass("pass a condition", passFunc)
}
public func allPass<T,U where U: SequenceType, U.Generator.Element == T>
(passName:String, passFunc: (T?) -> Bool) -> NonNilMatcherFunc<U> {
return createAllPassMatcher() {
expression, failureMessage in
failureMessage.postfixMessage = passName
return passFunc(expression.evaluate())
}
}
public func allPass<U,V where U: SequenceType, V: NonNilBasicMatcher, U.Generator.Element == V.ValueType>
(matcher: V) -> NonNilMatcherFunc<U> {
let wrapper = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(matcher))
return createAllPassMatcher() {wrapper.matches($0, failureMessage: $1)}
}
public func allPass<U,V where U: SequenceType, V: BasicMatcher, U.Generator.Element == V.ValueType>
(matcher: V) -> NonNilMatcherFunc<U> {
let wrapper = BasicMatcherWrapper(matcher: matcher)
return createAllPassMatcher() {wrapper.matches($0, failureMessage: $1)}
}
public func allPass<U,V where U: SequenceType, V: Matcher, U.Generator.Element == V.ValueType>
(matcher: V) -> NonNilMatcherFunc<U> {
return createAllPassMatcher() {matcher.matches($0, failureMessage: $1)}
}
private func createAllPassMatcher<T,U where U: SequenceType, U.Generator.Element == T>
(elementEvaluator:(Expression<T>, FailureMessage) -> Bool) -> NonNilMatcherFunc<U> {
return NonNilMatcherFunc { actualExpression, failureMessage in
failureMessage.actualValue = nil
if let actualValue = actualExpression.evaluate() {
for currentElement in actualValue {
let exp = Expression(
expression: {currentElement}, location: actualExpression.location)
if !elementEvaluator(exp, failureMessage) {
failureMessage.postfixMessage =
"all \(failureMessage.postfixMessage),"
+ " but failed first at element <\(stringify(currentElement))>"
+ " in <\(stringify(actualValue))>"
return false
}
}
failureMessage.postfixMessage = "all \(failureMessage.postfixMessage)"
} else {
failureMessage.postfixMessage = "all pass (use beNil() to match nils)"
return false
}
return true
}
}
extension NMBObjCMatcher {
public class func allPassMatcher(matcher: NMBObjCMatcher) -> NMBObjCMatcher {
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
let actualValue = actualExpression.evaluate()
var nsObjects = [NSObject]()
var collectionIsUsable = true
if let value = actualValue as? NSFastEnumeration {
let generator = NSFastGenerator(value)
while let obj:AnyObject = generator.next() {
if let nsObject = obj as? NSObject {
nsObjects.append(nsObject)
} else {
collectionIsUsable = false
break
}
}
} else {
collectionIsUsable = false
}
if !collectionIsUsable {
failureMessage.postfixMessage =
"allPass only works with NSFastEnumeration (NSArray, NSSet, ...) of NSObjects"
failureMessage.expected = ""
failureMessage.to = ""
return false
}
let expr = Expression(expression: ({ nsObjects }), location: location)
let elementEvaluator: (Expression<NSObject>, FailureMessage) -> Bool = {
expression, failureMessage in
return matcher.matches(
{expression.evaluate()}, failureMessage: failureMessage, location: expr.location)
}
return createAllPassMatcher(elementEvaluator).matches(
expr, failureMessage: failureMessage)
}
}
}

View File

@ -30,7 +30,7 @@ public func >(lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
extension NMBObjCMatcher {
public class func beGreaterThanMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
let expr = actualExpression.cast { $0 as NMBComparable? }
let expr = actualExpression.cast { $0 as? NMBComparable }
return beGreaterThan(expected).matches(expr, failureMessage: failureMessage)
}
}

View File

@ -32,7 +32,7 @@ public func >=<T: NMBComparable>(lhs: Expectation<T>, rhs: T) {
extension NMBObjCMatcher {
public class func beGreaterThanOrEqualToMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
let expr = actualExpression.cast { $0 as NMBComparable? }
let expr = actualExpression.cast { $0 as? NMBComparable }
return beGreaterThanOrEqualTo(expected).matches(expr, failureMessage: failureMessage)
}
}

View File

@ -29,7 +29,7 @@ public func <(lhs: Expectation<NMBComparable>, rhs: NMBComparable?) {
extension NMBObjCMatcher {
public class func beLessThanMatcher(expected: NMBComparable?) -> NMBObjCMatcher {
return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage, location in
let expr = actualExpression.cast { $0 as NMBComparable? }
let expr = actualExpression.cast { $0 as! NMBComparable? }
return beLessThan(expected).matches(expr, failureMessage: failureMessage)
}
}

View File

@ -43,7 +43,7 @@ extension NMBObjCMatcher {
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)
return beginWith(expected as! String).matches(expr, failureMessage: failureMessage)
} else {
let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
return beginWith(expected).matches(expr, failureMessage: failureMessage)

View File

@ -28,6 +28,19 @@ public func contain(substrings: String...) -> NonNilMatcherFunc<String> {
}
}
/// A Nimble matcher that succeeds when the actual string contains the expected substring.
public func contain(substrings: NSString...) -> NonNilMatcherFunc<NSString> {
return NonNilMatcherFunc { actualExpression, failureMessage in
failureMessage.postfixMessage = "contain <\(arrayAsString(substrings))>"
if let actual = actualExpression.evaluate() {
return all(substrings) {
return actual.containsString($0.description)
}
}
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
@ -48,7 +61,7 @@ extension NMBObjCMatcher {
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)
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 {

View File

@ -53,7 +53,7 @@ extension NMBObjCMatcher {
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)
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)

View File

@ -50,6 +50,52 @@ public func equal<T: Equatable>(expectedValue: [T]?) -> NonNilMatcherFunc<[T]> {
}
}
/// A Nimble matcher that succeeds when the actual set is equal to the expected set.
public func equal<T>(expectedValue: Set<T>?) -> NonNilMatcherFunc<Set<T>> {
return equal(expectedValue, stringify: stringify)
}
/// A Nimble matcher that succeeds when the actual set is equal to the expected set.
public func equal<T: Comparable>(expectedValue: Set<T>?) -> NonNilMatcherFunc<Set<T>> {
return equal(expectedValue, stringify: {
if let set = $0 {
return stringify(Array(set).sorted { $0 < $1 })
} else {
return "nil"
}
})
}
private func equal<T>(expectedValue: Set<T>?, #stringify: Set<T>? -> String) -> NonNilMatcherFunc<Set<T>> {
return NonNilMatcherFunc { actualExpression, failureMessage in
failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>"
if let expectedValue = expectedValue {
if let actualValue = actualExpression.evaluate() {
failureMessage.actualValue = "<\(stringify(actualValue))>"
if expectedValue == actualValue {
return true
}
let missing = expectedValue.subtract(actualValue)
if missing.count > 0 {
failureMessage.postfixActual += ", missing <\(stringify(missing))>"
}
let extra = actualValue.subtract(expectedValue)
if extra.count > 0 {
failureMessage.postfixActual += ", extra <\(stringify(extra))>"
}
}
} else {
failureMessage.postfixActual = " (use beNil() to match nils)"
}
return false
}
}
public func ==<T: Equatable>(lhs: Expectation<T>, rhs: T?) {
lhs.to(equal(rhs))
}
@ -66,6 +112,22 @@ public func !=<T: Equatable>(lhs: Expectation<[T]>, rhs: [T]?) {
lhs.toNot(equal(rhs))
}
public func ==<T>(lhs: Expectation<Set<T>>, rhs: Set<T>?) {
lhs.to(equal(rhs))
}
public func !=<T>(lhs: Expectation<Set<T>>, rhs: Set<T>?) {
lhs.toNot(equal(rhs))
}
public func ==<T: Comparable>(lhs: Expectation<Set<T>>, rhs: Set<T>?) {
lhs.to(equal(rhs))
}
public func !=<T: Comparable>(lhs: Expectation<Set<T>>, rhs: Set<T>?) {
lhs.toNot(equal(rhs))
}
public func ==<T: Equatable, C: Equatable>(lhs: Expectation<[T: C]>, rhs: [T: C]?) {
lhs.to(equal(rhs))
}

View File

@ -20,7 +20,7 @@ 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)
return match(expected.description).matches(actual, failureMessage: failureMessage)
}
}
}

View File

@ -82,11 +82,11 @@ extension NSDecimalNumber : NMBDoubleConvertible { } // TODO: not the best to do
}
extension NSNumber : NMBComparable {
public func NMB_compare(otherObject: NMBComparable!) -> NSComparisonResult {
return compare(otherObject as NSNumber)
return compare(otherObject as! NSNumber)
}
}
extension NSString : NMBComparable {
public func NMB_compare(otherObject: NMBComparable!) -> NSComparisonResult {
return compare(otherObject as NSString)
return compare(otherObject as! String)
}
}

View File

@ -1,81 +1,185 @@
import Foundation
internal func raiseExceptionMatcher<T>(message: String, matches: (NSException?) -> Bool) -> MatcherFunc<T> {
internal struct RaiseExceptionMatchResult {
var success: Bool
var nameFailureMessage: FailureMessage?
var reasonFailureMessage: FailureMessage?
var userInfoFailureMessage: FailureMessage?
}
internal func raiseExceptionMatcher(matches: (NSException?, SourceLocation) -> RaiseExceptionMatchResult) -> MatcherFunc<Any> {
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)
}), finally: nil)
capture.tryBlock {
actualExpression.evaluate()
return
}
return matches(exception)
let result = matches(exception, actualExpression.location)
failureMessage.postfixMessage = "raise exception"
if let nameFailureMessage = result.nameFailureMessage {
failureMessage.postfixMessage += " with name \(nameFailureMessage.postfixMessage)"
}
if let reasonFailureMessage = result.reasonFailureMessage {
failureMessage.postfixMessage += " with reason \(reasonFailureMessage.postfixMessage)"
}
if let userInfoFailureMessage = result.userInfoFailureMessage {
failureMessage.postfixMessage += " with userInfo \(userInfoFailureMessage.postfixMessage)"
}
if result.nameFailureMessage == nil && result.reasonFailureMessage == nil
&& result.userInfoFailureMessage == nil {
failureMessage.postfixMessage = "raise any exception"
}
return result.success
}
}
// A Nimble matcher that succeeds when the actual expression raises an exception, which name,
// reason and userInfo match successfully with the provided matchers
public func raiseException(
named: NonNilMatcherFunc<String>? = nil,
reason: NonNilMatcherFunc<String>? = nil,
userInfo: NonNilMatcherFunc<NSDictionary>? = nil) -> MatcherFunc<Any> {
return raiseExceptionMatcher() { exception, location in
var matches = exception != nil
var nameFailureMessage: FailureMessage?
if let nameMatcher = named {
let wrapper = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(nameMatcher))
nameFailureMessage = FailureMessage()
matches = wrapper.matches(
Expression(expression: { exception?.name },
location: location,
isClosure: false),
failureMessage: nameFailureMessage!) && matches
}
var reasonFailureMessage: FailureMessage?
if let reasonMatcher = reason {
let wrapper = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(reasonMatcher))
reasonFailureMessage = FailureMessage()
matches = wrapper.matches(
Expression(expression: { exception?.reason },
location: location,
isClosure: false),
failureMessage: reasonFailureMessage!) && matches
}
var userInfoFailureMessage: FailureMessage?
if let userInfoMatcher = userInfo {
let wrapper = NonNilMatcherWrapper(NonNilBasicMatcherWrapper(userInfoMatcher))
userInfoFailureMessage = FailureMessage()
matches = wrapper.matches(
Expression(expression: { exception?.userInfo },
location: location,
isClosure: false),
failureMessage: userInfoFailureMessage!) && matches
}
return RaiseExceptionMatchResult(
success: matches,
nameFailureMessage: nameFailureMessage,
reasonFailureMessage: reasonFailureMessage,
userInfoFailureMessage: userInfoFailureMessage)
}
}
/// 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
}
return raiseException(named: equal(named), reason: equal(reason), userInfo: equal(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
}
return raiseException(named: equal(named), reason: equal(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
}
return raiseException(named: equal(named))
}
@objc public class NMBObjCRaiseExceptionMatcher : NMBMatcher {
var _name: String?
var _reason: String?
var _userInfo: NSDictionary?
var _nameMatcher: NMBMatcher?
var _reasonMatcher: NMBMatcher?
var _userInfoMatcher: NMBMatcher?
init(name: String?, reason: String?, userInfo: NSDictionary?) {
_name = name
_reason = reason
_userInfo = userInfo
}
init(nameMatcher: NMBMatcher?, reasonMatcher: NMBMatcher?, userInfoMatcher: NMBMatcher?) {
_nameMatcher = nameMatcher
_reasonMatcher = reasonMatcher
_userInfoMatcher = userInfoMatcher
}
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)
if _nameMatcher != nil || _reasonMatcher != nil || _userInfoMatcher != nil {
return raiseExceptionMatcher() {
exception, location in
var matches = exception != nil
var nameFailureMessage: FailureMessage?
if let nameMatcher = self._nameMatcher {
nameFailureMessage = FailureMessage()
matches = nameMatcher.matches({ exception?.name },
failureMessage: nameFailureMessage!,
location: location) && matches
}
var reasonFailureMessage: FailureMessage?
if let reasonMatcher = self._reasonMatcher {
reasonFailureMessage = FailureMessage()
matches = reasonMatcher.matches({ exception?.reason },
failureMessage: reasonFailureMessage!,
location: location) && matches
}
var userInfoFailureMessage: FailureMessage?
if let userInfoMatcher = self._userInfoMatcher {
userInfoFailureMessage = FailureMessage()
matches = userInfoMatcher.matches({ exception?.userInfo },
failureMessage: userInfoFailureMessage!,
location: location) && matches
}
return RaiseExceptionMatchResult(
success: matches,
nameFailureMessage: nameFailureMessage,
reasonFailureMessage: reasonFailureMessage,
userInfoFailureMessage: userInfoFailureMessage)
}.matches(expr, failureMessage: failureMessage)
} else if let name = _name, reason = _reason, userInfo = _userInfo {
return raiseException(named: name, reason: reason, userInfo: userInfo).matches(expr, failureMessage: failureMessage)
} else if let name = _name, reason = _reason {
return raiseException(named: name, reason: reason).matches(expr, failureMessage: failureMessage)
} else if let name = _name {
return raiseException(named: name).matches(expr, failureMessage: failureMessage)
} else {
return raiseException().matches(expr, failureMessage: failureMessage)
}
@ -102,6 +206,27 @@ public func raiseException() -> MatcherFunc<Any> {
return NMBObjCRaiseExceptionMatcher(name: self._name, reason: self._reason, userInfo: userInfo)
})
}
public var withName: (nameMatcher: NMBMatcher) -> NMBObjCRaiseExceptionMatcher {
return ({ nameMatcher in
return NMBObjCRaiseExceptionMatcher(nameMatcher: nameMatcher,
reasonMatcher: self._reasonMatcher, userInfoMatcher: self._userInfoMatcher)
})
}
public var withReason: (reasonMatcher: NMBMatcher) -> NMBObjCRaiseExceptionMatcher {
return ({ reasonMatcher in
return NMBObjCRaiseExceptionMatcher(nameMatcher: self._nameMatcher,
reasonMatcher: reasonMatcher, userInfoMatcher: self._userInfoMatcher)
})
}
public var withUserInfo: (userInfoMatcher: NMBMatcher) -> NMBObjCRaiseExceptionMatcher {
return ({ userInfoMatcher in
return NMBObjCRaiseExceptionMatcher(nameMatcher: self._nameMatcher,
reasonMatcher: self._reasonMatcher, userInfoMatcher: userInfoMatcher)
})
}
}
extension NMBObjCMatcher {

View File

@ -5,7 +5,7 @@ internal func identityAsString(value: AnyObject?) -> String {
if value == nil {
return "nil"
}
return NSString(format: "<%p>", unsafeBitCast(value!, Int.self))
return NSString(format: "<%p>", unsafeBitCast(value!, Int.self)).description
}
internal func arrayAsString<T>(items: [T], joiner: String = ", ") -> String {
@ -41,8 +41,8 @@ extension NSArray : NMBStringer {
}
internal func stringify<T>(value: T) -> String {
if value is Double {
return NSString(format: "%.4f", (value as Double))
if let value = value as? Double {
return NSString(format: "%.4f", (value)).description
}
return toString(value)
}

View File

@ -2,8 +2,14 @@ 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
let timeoutInterval: NSTimeInterval
let pollInterval: NSTimeInterval
init(fullMatcher: U, timeoutInterval: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {
self.fullMatcher = fullMatcher
self.timeoutInterval = timeoutInterval
self.pollInterval = pollInterval
}
func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
let uncachedExpression = actualExpression.withoutCaching()
@ -34,25 +40,36 @@ struct AsyncMatcherWrapper<T, U where U: Matcher, U.ValueType == T>: Matcher {
}
}
private let toEventuallyRequiresClosureError = "expect(...).toEventually(...) requires an explicit closure (eg - expect { ... }.toEventually(...) )\nSwift 1.2 @autoclosure behavior has changed in an incompatible way for Nimble to function"
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))
if expression.isClosure {
to(AsyncMatcherWrapper(
fullMatcher: FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
timeoutInterval: timeout,
pollInterval: pollInterval))
} else {
verify(false, toEventuallyRequiresClosureError)
}
}
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))
if expression.isClosure {
toNot(AsyncMatcherWrapper(
fullMatcher: FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
timeoutInterval: timeout,
pollInterval: pollInterval))
} else {
verify(false, toEventuallyRequiresClosureError)
}
}
public func toEventually<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.01) {

View File

@ -96,6 +96,10 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_match(id expectedValue);
NIMBLE_SHORT(id<NMBMatcher> match(id expectedValue),
NMB_match(expectedValue));
NIMBLE_EXPORT id<NMBMatcher> NMB_allPass(id matcher);
NIMBLE_SHORT(id<NMBMatcher> allPass(id matcher),
NMB_allPass(matcher));
// 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.

View File

@ -84,18 +84,22 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_match(id expectedValue) {
return [NMBObjCMatcher matchMatcher:expectedValue];
}
NIMBLE_EXPORT id<NMBMatcher> NMB_allPass(id expectedValue) {
return [NMBObjCMatcher allPassMatcher: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];
[NMBWait untilTimeout:timeout file:file line:line action:action];
};
}
NIMBLE_EXPORT NMBWaitUntilBlock nmb_wait_until_builder(NSString *file, NSUInteger line) {
return ^(void (^action)(void (^)(void))) {
[NMBWait until:action file:file line:line];
[NMBWait untilFile:file line:line action:action];
};
}

102
Pods/Nimble/README.md generated
View File

@ -1,6 +1,6 @@
# Nimble
[![Build Status](https://travis-ci.org/Quick/Nimble.svg?branch=master)](https://travis-ci.org/Quick/Nimble)
[![Build Status](https://travis-ci.org/Quick/Nimble.svg?branch=swift-1.1)](https://travis-ci.org/Quick/Nimble)
Use Nimble to express the expected outcomes of Swift
or Objective-C expressions. Inspired by
@ -40,6 +40,7 @@ expect(ocean.isClean).toEventually(beTruthy())
- [Exceptions](#exceptions)
- [Collection Membership](#collection-membership)
- [Strings](#strings)
- [Checking if all elements of a collection pass a condition](#checking-if-all-elements-of-a-collection-pass-a-condition)
- [Writing Your Own Matchers](#writing-your-own-matchers)
- [Lazy Evaluation](#lazy-evaluation)
- [Type Checking via Swift Generics](#type-checking-via-swift-generics)
@ -177,14 +178,14 @@ let exception = NSException(
name: NSInternalInconsistencyException,
reason: "Not enough fish in the sea.",
userInfo: ["something": "is fishy"])
expect(exception.raise()).to(raiseException())
expect { exception.raise() }.to(raiseException())
// Also, you can customize raiseException to be more specific
expect(exception.raise()).to(raiseException(named: NSInternalInconsistencyException))
expect(exception.raise()).to(raiseException(
expect { exception.raise() }.to(raiseException(named: NSInternalInconsistencyException))
expect { exception.raise() }.to(raiseException(
named: NSInternalInconsistencyException,
reason: "Not enough fish in the sea"))
expect(exception.raise()).to(raiseException(
expect { exception.raise() }.to(raiseException(
named: NSInternalInconsistencyException,
reason: "Not enough fish in the sea",
userInfo: ["something": "is fishy"]))
@ -213,16 +214,6 @@ expectAction([exception raise]).to(raiseException().
userInfo(@{@"something": @"is fishy"}));
```
In Swift, the `expect` function can also take a trailing closure:
```swift
// Swift
expect {
exception.raise()
}.to(raiseException(named: NSInternalInconsistencyException))
```
## C Primitives
Some testing frameworks make it hard to test primitive C values.
@ -639,6 +630,16 @@ expect(actual).to(raiseException(named: name))
// Passes if actual raises an exception with the given name and reason:
expect(actual).to(raiseException(named: name, reason: reason))
// Passes if actual raises an exception with a name equal "a name"
expect(actual).to(raiseException(named: equal("a name")))
// Passes if actual raises an exception with a reason that begins with "a r"
expect(actual).to(raiseException(reason: beginWith("a r")))
// Passes if actual raises an exception with a name equal "a name"
// and a reason that begins with "a r"
expect(actual).to(raiseException(named: equal("a name"), reason: beginWith("a r")))
```
```objc
@ -646,13 +647,27 @@ expect(actual).to(raiseException(named: name, reason: reason))
// Passes if actual, when evaluated, raises an exception:
expect(actual).to(raiseException())
// Passes if actual raises an exception with the given name
expect(actual).to(raiseException().named(name))
// Passes if actual raises an exception with the given name and reason:
expect(actual).to(raiseException().named(name).reason(reason))
// Passes if actual raises an exception with a name equal "a name"
expect(actual).to(raiseException().withName(equal("a name")))
// Passes if actual raises an exception with a reason that begins with "a r"
expect(actual).to(raiseException().withName(withReason(beginWith(@"a r")))
// Passes if actual raises an exception with a name equal "a name"
// and a reason that begins with "a r"
expect(actual).to(raiseException().withName(equal("a name")).withReason(beginWith(@"a r")))
```
Note: Swift currently doesn't have exceptions. Only Objective-C code can raise
exceptions that Nimble will catch.
> Sorry, [Nimble doesn't support matching on exception `name`, `reason`, or `userInfo` yet](https://github.com/Quick/Nimble/issues/26).
## Collection Membership
```swift
@ -768,6 +783,29 @@ expect(actual).to(beEmpty());
expect(actual).to(match(expected))
```
## Checking if all elements of a collection pass a condition
```swift
// Swift
// with a custom function:
expect([1,2,3,4]).to(allPass({$0 < 5}))
// with another matcher:
expect([1,2,3,4]).to(allPass(beLessThan(5)))
```
```objc
// Objective-C
expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5)));
```
For Swift the actual value has to be a SequenceType, e.g. an array, a set or a custom seqence type.
For Objective-C the actual value has to be a NSFastEnumeration, e.g. NSArray and NSSet, of NSObjects and only the variant which
uses another matcher is available here.
# Writing Your Own Matchers
In Nimble, matchers are Swift functions that take an expected
@ -807,9 +845,10 @@ also check out the tips below.
## Lazy Evaluation
`actualExpression` is a lazy, memoized closure around the value provided to
the `expect` function. In order to determine whether that value matches,
custom matchers should call `actualExpression.evalaute()`:
`actualExpression` is a lazy, memoized closure around the value provided to the
`expect` function. The expression can either be a closure or a value directly
passed to `expect(...)`. In order to determine whether that value matches,
custom matchers should call `actualExpression.evaluate()`:
```swift
// Swift
@ -827,6 +866,9 @@ that returns a value. The value it returns, which is accessed via the
`evaluate()` method, may be `nil`. If that value is `nil`, the `beNil`
matcher function returns `true`, indicating that the expectation passed.
Use `expression.isClosure` to determine if the expression will be invoking
a closure to produce its value.
## Type Checking via Swift Generics
Using Swift's generics, matchers can constrain the type of the actual value
@ -971,8 +1013,9 @@ extension NMBObjCMatcher {
Quick and Nimble, follow [the installation instructions in the Quick
README](https://github.com/Quick/Quick#how-to-install-quick).
Nimble can currently be installed in one of two ways: using a pre-release
version of CocoaPods, or with git submodules.
Nimble can currently be installed in one of two ways: using CocoaPods, or with git submodules. The master branch of
Nimble supports Swift 1.2. For Swift 1.1 support, use the `swift-1.1`
branch.
## Installing Nimble as a Submodule
@ -980,7 +1023,7 @@ To use Nimble as a submodule to test your iOS or OS X applications, follow these
4 easy steps:
1. Clone the Nimble repository
2. Add Nimble.xcodeproj to your test target
2. Add Nimble.xcodeproj to the Xcode workspace for your project
3. Link Nimble.framework to your test target
4. Start writing expectations!
@ -991,9 +1034,8 @@ install just Nimble.
## Installing Nimble via CocoaPods
To use Nimble in CocoaPods to test your iOS or OS X applications, we'll need to
install 0.36 Beta 1 of CocoaPods. Do so using the command `[sudo] gem install cocoapods --pre`.
Then just add Nimble to your podfile.
To use Nimble in CocoaPods to test your iOS or OS X applications, update CocoaPods to Version 0.36.0.
Then add Nimble to your podfile and add the ```use_frameworks!``` line to enable Swift support for Cocoapods.
```ruby
platform :ios, '8.0'
@ -1003,8 +1045,12 @@ source 'https://github.com/CocoaPods/Specs.git'
# Whatever pods you need for your app go here
target 'YOUR_APP_NAME_HERE_Tests', :exclusive => true do
pod 'Nimble'
use_frameworks!
# If you're using Swift 1.2 (Xcode 6.3 beta), use this:
pod 'Nimble', '~> 0.4.0'
# Otherwise, use this commented out line for Swift 1.1 (Xcode 6.2):
# pod 'Nimble', '~> 0.3.0'
end
```
Finally run `bundle exec pod install`.
Finally run `pod install`.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "03098993B86EADB31B473BE6"
BlueprintIdentifier = "F31DCF4BC1F75A477673D8D8"
BuildableName = "Nimble.framework"
BlueprintName = "Pods-cameraTests-Nimble"
ReferencedContainer = "container:Pods.xcodeproj">

View File

@ -1,59 +0,0 @@
<?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>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0640"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13DE2AA1E6F090FB14C78F4F"
BlueprintIdentifier = "5450F12D18236260DBDC1426"
BuildableName = "Pods_cameraTests.framework"
BlueprintName = "Pods-cameraTests"
ReferencedContainer = "container:Pods.xcodeproj">

View File

@ -9,11 +9,6 @@
<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>
@ -22,17 +17,12 @@
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>03098993B86EADB31B473BE6</key>
<key>5450F12D18236260DBDC1426</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>13DE2AA1E6F090FB14C78F4F</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>63EE31CFA4335E182795B62C</key>
<key>F31DCF4BC1F75A477673D8D8</key>
<dict>
<key>primary</key>
<true/>

201
Pods/Quick/LICENSE generated
View File

@ -1,201 +0,0 @@
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.

View File

@ -1,28 +0,0 @@
/**
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
}

View File

@ -1,147 +0,0 @@
/**
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)
}
}

View File

@ -1,30 +0,0 @@
#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

View File

@ -1,83 +0,0 @@
#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

View File

@ -1,227 +0,0 @@
/**
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)
}

View File

@ -1,211 +0,0 @@
#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);

View File

@ -1,70 +0,0 @@
#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);
}

View File

@ -1,100 +0,0 @@
/**
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)")
}
}

View File

@ -1,103 +0,0 @@
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
}

View File

@ -1,97 +0,0 @@
/**
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
}
}
}

View File

@ -1,22 +0,0 @@
/**
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
}
}

View File

@ -1,16 +0,0 @@
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)
}
}

View File

@ -1,29 +0,0 @@
/**
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"
}
}

View File

@ -1,35 +0,0 @@
// 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

View File

@ -1,36 +0,0 @@
/**
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)
}
}
}

View File

@ -1,34 +0,0 @@
/**
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
}
}

View File

@ -1,17 +0,0 @@
#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

View File

@ -1,33 +0,0 @@
#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

View File

@ -1,13 +0,0 @@
#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>

View File

@ -1,48 +0,0 @@
#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

View File

@ -1,142 +0,0 @@
#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

View File

@ -1,197 +0,0 @@
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()
}
}
}

1165
Pods/Quick/README.md generated

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.3.0</string>
<string>0.4.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -2,7 +2,7 @@
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"
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Nimble" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Nimble"
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

View File

@ -1,26 +0,0 @@
<?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.2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -1,10 +0,0 @@
#include "Pods-cameraTests-Quick.xcconfig"
CONFIGURATION_BUILD_DIR = $PODS_FRAMEWORK_BUILD_PATH
FRAMEWORK_SEARCH_PATHS = "$PODS_FRAMEWORK_BUILD_PATH" ${PODS_CAMERATESTS_QUICK_FRAMEWORK_SEARCH_PATHS}
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Quick" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Nimble" "${PODS_ROOT}/Headers/Public/Quick"
OTHER_LDFLAGS = ${PODS_CAMERATESTS_QUICK_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

View File

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_cameraTests_Quick : NSObject
@end
@implementation PodsDummy_Pods_cameraTests_Quick
@end

View File

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-cameraTests-environment.h"

View File

@ -1,11 +0,0 @@
#import <UIKit/UIKit.h>
#import "NSString+QCKSelectorName.h"
#import "Quick.h"
#import "QuickSpec.h"
#import "QuickConfiguration.h"
#import "QCKDSL.h"
FOUNDATION_EXPORT double QuickVersionNumber;
FOUNDATION_EXPORT const unsigned char QuickVersionString[];

View File

@ -1,6 +0,0 @@
framework module Quick {
umbrella header "Pods-cameraTests-Quick-umbrella.h"
export *
module * { export * }
}

View File

@ -1,2 +0,0 @@
PODS_CAMERATESTS_QUICK_FRAMEWORK_SEARCH_PATHS = $(inherited) "$(SDKROOT)/Developer/Library/Frameworks" "$(PLATFORM_DIR)/Developer/Library/Frameworks"
PODS_CAMERATESTS_QUICK_OTHER_LDFLAGS = -framework "XCTest"

View File

@ -205,209 +205,4 @@ Apache License
See the License for the specific language governing permissions and
limitations under the License.
## Quick
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.
Generated by CocoaPods - http://cocoapods.org

View File

@ -221,215 +221,6 @@
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>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.
</string>
<key>Title</key>
<string>Quick</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>

View File

@ -9,12 +9,6 @@
// Nimble
#define COCOAPODS_POD_AVAILABLE_Nimble
#define COCOAPODS_VERSION_MAJOR_Nimble 0
#define COCOAPODS_VERSION_MINOR_Nimble 3
#define COCOAPODS_VERSION_PATCH_Nimble 0
// Quick
#define COCOAPODS_POD_AVAILABLE_Quick
#define COCOAPODS_VERSION_MAJOR_Quick 0
#define COCOAPODS_VERSION_MINOR_Quick 2
#define COCOAPODS_VERSION_PATCH_Quick 2
#define COCOAPODS_VERSION_MINOR_Nimble 4
#define COCOAPODS_VERSION_PATCH_Nimble 2

View File

@ -17,8 +17,8 @@ install_framework()
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" ${source} ${destination}"
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" "${source}" "${destination}"
echo "rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" --filter "- Modules/" ${source} ${destination}"
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" --filter "- Modules/" "${source}" "${destination}"
# Resign the code if required by the build settings to avoid unstable apps
if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
code_sign "${destination}/$1"
@ -49,9 +49,7 @@ code_sign() {
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework 'Nimble.framework'
install_framework 'Quick.framework'
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework 'Nimble.framework'
install_framework 'Quick.framework'
fi

View File

@ -6,7 +6,13 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
XCASSET_FILES=""
XCASSET_FILES=()
realpath() {
DIRECTORY=$(cd "${1%/*}" && pwd)
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
@ -38,7 +44,8 @@ install_resource()
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
XCASSET_FILES="$XCASSET_FILES '$1'"
ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1")
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
/*)
echo "$1"
@ -57,7 +64,7 @@ if [[ "${ACTION}" == "install" ]]; then
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n $XCASSET_FILES ]
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
@ -73,5 +80,14 @@ then
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
echo $XCASSET_FILES | xargs actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi

View File

@ -1,8 +1,8 @@
FRAMEWORK_SEARCH_PATHS = "$PODS_FRAMEWORK_BUILD_PATH"
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/Nimble.framework/Headers" -iquote "$PODS_FRAMEWORK_BUILD_PATH/Quick.framework/Headers"
OTHER_LDFLAGS = $(inherited) -ObjC -framework "Nimble" -framework "Quick"
OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/Nimble.framework/Headers"
OTHER_LDFLAGS = $(inherited) -ObjC -framework "Nimble"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-cameraTests

View File

@ -1,8 +1,8 @@
FRAMEWORK_SEARCH_PATHS = "$PODS_FRAMEWORK_BUILD_PATH"
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_FRAMEWORK_BUILD_PATH"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/Nimble.framework/Headers" -iquote "$PODS_FRAMEWORK_BUILD_PATH/Quick.framework/Headers"
OTHER_LDFLAGS = $(inherited) -ObjC -framework "Nimble" -framework "Quick"
OTHER_CFLAGS = $(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/Nimble.framework/Headers"
OTHER_LDFLAGS = $(inherited) -ObjC -framework "Nimble"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-cameraTests

View File

@ -1,16 +1,7 @@
//
// cameraTests.swift
// cameraTests
//
// Created by Natalia Terlecka on 25/03/15.
// Copyright (c) 2015 imaginaryCloud. All rights reserved.
//
import UIKit
import XCTest
import Quick
class cameraTests: XCTestCase {
override func setUp() {