init iOS module
This commit is contained in:
201
iOS/Example/Pods/Quick/LICENSE
generated
Normal file
201
iOS/Example/Pods/Quick/LICENSE
generated
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014, Quick Team
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
88
iOS/Example/Pods/Quick/README.md
generated
Normal file
88
iOS/Example/Pods/Quick/README.md
generated
Normal file
@@ -0,0 +1,88 @@
|
||||

|
||||
|
||||
[](https://travis-ci.org/Quick/Quick)
|
||||
[](https://cocoapods.org/pods/Quick)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://cocoapods.org/pods/Quick)
|
||||
|
||||
Quick is a behavior-driven development framework for Swift and Objective-C.
|
||||
Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo).
|
||||
|
||||

|
||||
|
||||
```swift
|
||||
// Swift
|
||||
|
||||
import Quick
|
||||
import Nimble
|
||||
|
||||
class TableOfContentsSpec: QuickSpec {
|
||||
override func spec() {
|
||||
describe("the 'Documentation' directory") {
|
||||
it("has everything you need to get started") {
|
||||
let sections = Directory("Documentation").sections
|
||||
expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups"))
|
||||
expect(sections).to(contain("Installing Quick"))
|
||||
}
|
||||
|
||||
context("if it doesn't have what you're looking for") {
|
||||
it("needs to be updated") {
|
||||
let you = You(awesome: true)
|
||||
expect{you.submittedAnIssue}.toEventually(beTruthy())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
#### Nimble
|
||||
Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md).
|
||||
|
||||
## Swift Version
|
||||
|
||||
Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project.
|
||||
|
||||
|Swift version |Quick version |Nimble version |
|
||||
|:--------------------|:---------------|:--------------|
|
||||
|Swift 3 |v1.0.0 or later |v5.0.0 or later|
|
||||
|Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 |
|
||||
|
||||
## Documentation
|
||||
|
||||
All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile:
|
||||
|
||||
```rb
|
||||
# Podfile
|
||||
|
||||
use_frameworks!
|
||||
|
||||
target "MyApp" do
|
||||
# Normal libraries
|
||||
|
||||
abstract_target 'Tests' do
|
||||
inherit! :search_paths
|
||||
target "MyAppTests"
|
||||
target "MyAppUITests"
|
||||
|
||||
pod 'Quick'
|
||||
pod 'Nimble'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Projects using Quick
|
||||
|
||||
Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them.
|
||||
|
||||
Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick).
|
||||
|
||||
## Who uses Quick
|
||||
|
||||
Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses?
|
||||
|
||||
Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details.
|
||||
17
iOS/Example/Pods/Quick/Sources/Quick/Behavior.swift
generated
Normal file
17
iOS/Example/Pods/Quick/Sources/Quick/Behavior.swift
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` function with a context instance of the generic type.
|
||||
*/
|
||||
|
||||
open class Behavior<Context> {
|
||||
|
||||
open static var name: String { return String(describing: self) }
|
||||
/**
|
||||
override this method in your behavior to define a set of reusable examples.
|
||||
|
||||
This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach`
|
||||
and `afterEach` closures, as well as any number of examples (defined using `it`).
|
||||
|
||||
- parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject.
|
||||
*/
|
||||
open class func spec(_ aContext: @escaping () -> Context) {}
|
||||
}
|
||||
45
iOS/Example/Pods/Quick/Sources/Quick/Callsite.swift
generated
Normal file
45
iOS/Example/Pods/Quick/Sources/Quick/Callsite.swift
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#else
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#endif
|
||||
#else
|
||||
public class _CallsiteBase: NSObject {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
An object encapsulating the file and line number at which
|
||||
a particular example is defined.
|
||||
*/
|
||||
final public class Callsite: _CallsiteBase {
|
||||
/**
|
||||
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: UInt
|
||||
|
||||
internal init(file: String, line: UInt) {
|
||||
self.file = file
|
||||
self.line = line
|
||||
}
|
||||
}
|
||||
|
||||
extension Callsite {
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
@nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool {
|
||||
return lhs.file == rhs.file && lhs.line == rhs.line
|
||||
}
|
||||
}
|
||||
161
iOS/Example/Pods/Quick/Sources/Quick/Configuration/Configuration.swift
generated
Normal file
161
iOS/Example/Pods/Quick/Sources/Quick/Configuration/Configuration.swift
generated
Normal file
@@ -0,0 +1,161 @@
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
A closure that temporarily exposes a Configuration object within
|
||||
the scope of the closure.
|
||||
*/
|
||||
public typealias QuickConfigurer = (_ configuration: Configuration) -> Void
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
final public class Configuration: NSObject {
|
||||
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.
|
||||
|
||||
- parameter 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: @escaping 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.
|
||||
|
||||
- parameter 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: @escaping 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.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
@objc(beforeEachWithMetadata:)
|
||||
public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
exampleHooks.appendBefore(closure)
|
||||
}
|
||||
#else
|
||||
public func beforeEach(_ closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
exampleHooks.appendBefore(closure)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
- parameter closure: The closure to be executed before each example
|
||||
in the test suite.
|
||||
*/
|
||||
public func beforeEach(_ closure: @escaping 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.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
@objc(afterEachWithMetadata:)
|
||||
public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
exampleHooks.appendAfter(closure)
|
||||
}
|
||||
#else
|
||||
public func afterEach(_ closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
exampleHooks.appendAfter(closure)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
- parameter closure: The closure to be executed before each example
|
||||
in the test suite.
|
||||
*/
|
||||
public func afterEach(_ closure: @escaping 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: @escaping 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: @escaping AfterSuiteClosure) {
|
||||
suiteHooks.appendAfter(closure)
|
||||
}
|
||||
}
|
||||
271
iOS/Example/Pods/Quick/Sources/Quick/DSL/DSL.swift
generated
Normal file
271
iOS/Example/Pods/Quick/Sources/Quick/DSL/DSL.swift
generated
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
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.
|
||||
|
||||
- parameter closure: The closure to be run prior to any examples in the test suite.
|
||||
*/
|
||||
public func beforeSuite(_ closure: @escaping 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.
|
||||
|
||||
- parameter closure: The closure to be run after all of the examples in the test suite.
|
||||
*/
|
||||
public func afterSuite(_ closure: @escaping 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.
|
||||
|
||||
- parameter name: The name of the shared example group. This must be unique across all shared example
|
||||
groups defined in a test suite.
|
||||
- parameter 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: @escaping () -> Void) {
|
||||
World.sharedWorld.sharedExamples(name) { _ in closure() }
|
||||
}
|
||||
|
||||
/**
|
||||
Defines a group of shared examples. These examples can be re-used in several locations
|
||||
by using the `itBehavesLike` function.
|
||||
|
||||
- parameter name: The name of the shared example group. This must be unique across all shared example
|
||||
groups defined in a test suite.
|
||||
- parameter 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: @escaping 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.
|
||||
|
||||
- parameter description: An arbitrary string describing the example group.
|
||||
- parameter closure: A closure that can contain other examples.
|
||||
- parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
*/
|
||||
public func describe(_ description: String, flags: FilterFlags = [:], closure: () -> Void) {
|
||||
World.sharedWorld.describe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example group. Equivalent to `describe`.
|
||||
*/
|
||||
public func context(_ description: String, flags: FilterFlags = [:], closure: () -> Void) {
|
||||
World.sharedWorld.context(description, flags: flags, closure: 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.
|
||||
|
||||
- parameter closure: The closure to be run prior to each example.
|
||||
*/
|
||||
public func beforeEach(_ closure: @escaping 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: @escaping 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.
|
||||
|
||||
- parameter closure: The closure to be run after each example.
|
||||
*/
|
||||
public func afterEach(_ closure: @escaping 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: @escaping AfterExampleWithMetadataClosure) {
|
||||
World.sharedWorld.afterEach(closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Defines an example. Examples use assertions to demonstrate how code should
|
||||
behave. These are like "tests" in XCTest.
|
||||
|
||||
- parameter description: An arbitrary string describing what the example is meant to specify.
|
||||
- parameter closure: A closure that can contain assertions.
|
||||
- parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
- parameter file: The absolute path to the file containing the example. A sensible default is provided.
|
||||
- parameter line: The line containing the example. A sensible default is provided.
|
||||
*/
|
||||
public func it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) {
|
||||
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.
|
||||
|
||||
- parameter 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.
|
||||
- parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
- parameter file: The absolute path to the file containing the current example group. A sensible default is provided.
|
||||
- parameter line: The line containing the current example group. A sensible default is provided.
|
||||
*/
|
||||
public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) {
|
||||
itBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] })
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
- parameter 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.
|
||||
- parameter sharedExampleContext: A closure that, when evaluated, returns key-value pairs that provide the
|
||||
shared examples with extra information on the subject of the example.
|
||||
- parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
- parameter file: The absolute path to the file containing the current example group. A sensible default is provided.
|
||||
- parameter line: The line containing the current example group. A sensible default is provided.
|
||||
*/
|
||||
public func itBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) {
|
||||
World.sharedWorld.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line)
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts the examples defined using a `Behavior` into the current example group.
|
||||
The shared examples are executed at this location, as if they were written out manually.
|
||||
This function also passes a strongly-typed context that can be evaluated to give the shared examples extra information on the subject of the example.
|
||||
|
||||
- parameter behavior: The type of `Behavior` class defining the example group to be executed.
|
||||
- parameter context: A closure that, when evaluated, returns an instance of `Behavior`'s context type to provide its example group with extra information on the subject of the example.
|
||||
- parameter flags: A mapping of string keys to booleans that can be used to filter examples or example groups.
|
||||
Empty by default.
|
||||
- parameter file: The absolute path to the file containing the current example group. A sensible default is provided.
|
||||
- parameter line: The line containing the current example group. A sensible default is provided.
|
||||
*/
|
||||
public func itBehavesLike<C>(_ behavior: Behavior<C>.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) {
|
||||
World.sharedWorld.itBehavesLike(behavior, context: context, 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.
|
||||
|
||||
- parameter description: An arbitrary string describing the example or example group.
|
||||
- parameter closure: A closure that will not be evaluated.
|
||||
*/
|
||||
public func pending(_ description: String, closure: () -> Void) {
|
||||
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, flags: FilterFlags, closure: () -> Void) {
|
||||
World.sharedWorld.xdescribe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly mark a `context` closure as pending.
|
||||
This disables all examples within the closure.
|
||||
*/
|
||||
public func xcontext(_ description: String, flags: FilterFlags, closure: () -> Void) {
|
||||
xdescribe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
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, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) {
|
||||
World.sharedWorld.xit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quicklu mark an `itBehavesLike` closure as pending.
|
||||
This disables the example group defined by this behavior and ensures the code within is never run.
|
||||
*/
|
||||
public func xitBehavesLike<C>(_ behavior: Behavior<C>.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) {
|
||||
World.sharedWorld.xitBehavesLike(behavior, context: context, flags: flags, file: file, line: line)
|
||||
}
|
||||
/**
|
||||
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, flags: FilterFlags = [:], closure: () -> Void) {
|
||||
World.sharedWorld.fdescribe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus a `context` closure. Equivalent to `fdescribe`.
|
||||
*/
|
||||
public func fcontext(_ description: String, flags: FilterFlags = [:], closure: () -> Void) {
|
||||
fdescribe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
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, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () -> Void) {
|
||||
World.sharedWorld.fit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus an `itBehavesLike` closure.
|
||||
*/
|
||||
public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line) {
|
||||
fitBehavesLike(name, flags: flags, file: file, line: line, sharedExampleContext: { return [:] })
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus an `itBehavesLike` closure.
|
||||
*/
|
||||
public func fitBehavesLike(_ name: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, sharedExampleContext: @escaping SharedExampleContext) {
|
||||
World.sharedWorld.fitBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line)
|
||||
}
|
||||
|
||||
/**
|
||||
Use this to quickly focus on `itBehavesLike` closure.
|
||||
*/
|
||||
public func fitBehavesLike<C>(_ behavior: Behavior<C>.Type, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, context: @escaping () -> C) {
|
||||
World.sharedWorld.fitBehavesLike(behavior, context: context, flags: flags, file: file, line: line)
|
||||
}
|
||||
205
iOS/Example/Pods/Quick/Sources/Quick/DSL/World+DSL.swift
generated
Normal file
205
iOS/Example/Pods/Quick/Sources/Quick/DSL/World+DSL.swift
generated
Normal file
@@ -0,0 +1,205 @@
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
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 {
|
||||
internal func beforeSuite(_ closure: @escaping BeforeSuiteClosure) {
|
||||
suiteHooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
internal func afterSuite(_ closure: @escaping AfterSuiteClosure) {
|
||||
suiteHooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
internal func sharedExamples(_ name: String, closure: @escaping SharedExampleClosure) {
|
||||
registerSharedExample(name, closure: closure)
|
||||
}
|
||||
|
||||
internal func describe(_ description: String, flags: FilterFlags, closure: () -> Void) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'describe' cannot be used inside '\(currentPhase)', 'describe' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
guard currentExampleGroup != nil else {
|
||||
raiseError("Error: example group was not created by its parent QuickSpec spec. Check that describe() or context() was used in QuickSpec.spec() and not a more general context (i.e. an XCTestCase test)")
|
||||
}
|
||||
let group = ExampleGroup(description: description, flags: flags)
|
||||
currentExampleGroup.appendExampleGroup(group)
|
||||
performWithCurrentExampleGroup(group, closure: closure)
|
||||
}
|
||||
|
||||
internal func context(_ description: String, flags: FilterFlags, closure: () -> Void) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'context' cannot be used inside '\(currentPhase)', 'context' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
self.describe(description, flags: flags, closure: closure)
|
||||
}
|
||||
|
||||
internal func fdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.describe(description, flags: focusedFlags, closure: closure)
|
||||
}
|
||||
|
||||
internal func xdescribe(_ description: String, flags: FilterFlags, closure: () -> Void) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.describe(description, flags: pendingFlags, closure: closure)
|
||||
}
|
||||
|
||||
internal func beforeEach(_ closure: @escaping BeforeExampleClosure) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'beforeEach' cannot be used inside '\(currentPhase)', 'beforeEach' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
currentExampleGroup.hooks.appendBefore(closure)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objc(beforeEachWithMetadata:)
|
||||
internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendBefore(closure)
|
||||
}
|
||||
#else
|
||||
internal func beforeEach(closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendBefore(closure)
|
||||
}
|
||||
#endif
|
||||
|
||||
internal func afterEach(_ closure: @escaping AfterExampleClosure) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'afterEach' cannot be used inside '\(currentPhase)', 'afterEach' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
currentExampleGroup.hooks.appendAfter(closure)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objc(afterEachWithMetadata:)
|
||||
internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendAfter(closure)
|
||||
}
|
||||
#else
|
||||
internal func afterEach(closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
currentExampleGroup.hooks.appendAfter(closure)
|
||||
}
|
||||
#endif
|
||||
|
||||
internal func it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
if beforesCurrentlyExecuting {
|
||||
raiseError("'it' cannot be used inside 'beforeEach', 'it' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
if aftersCurrentlyExecuting {
|
||||
raiseError("'it' cannot be used inside 'afterEach', 'it' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'it' cannot be used inside 'it', 'it' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
let callsite = Callsite(file: file, line: line)
|
||||
let example = Example(description: description, callsite: callsite, flags: flags, closure: closure)
|
||||
currentExampleGroup.appendExample(example)
|
||||
}
|
||||
|
||||
internal func fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.it(description, flags: focusedFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
internal func xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.it(description, flags: pendingFlags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
internal func itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
let callsite = Callsite(file: file, line: line)
|
||||
let closure = World.sharedWorld.sharedExample(name)
|
||||
|
||||
let group = ExampleGroup(description: name, flags: flags)
|
||||
currentExampleGroup.appendExampleGroup(group)
|
||||
performWithCurrentExampleGroup(group) {
|
||||
closure(sharedExampleContext)
|
||||
}
|
||||
|
||||
group.walkDownExamples { (example: Example) in
|
||||
example.isSharedExample = true
|
||||
example.callsite = callsite
|
||||
}
|
||||
}
|
||||
|
||||
internal func fitBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: focusedFlags, file: file, line: line)
|
||||
}
|
||||
|
||||
internal func itBehavesLike<C>(_ behavior: Behavior<C>.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) {
|
||||
guard currentExampleMetadata == nil else {
|
||||
raiseError("'itBehavesLike' cannot be used inside '\(currentPhase)', 'itBehavesLike' may only be used inside 'context' or 'describe'. ")
|
||||
}
|
||||
let callsite = Callsite(file: file, line: line)
|
||||
let closure = behavior.spec
|
||||
let group = ExampleGroup(description: behavior.name, flags: flags)
|
||||
currentExampleGroup.appendExampleGroup(group)
|
||||
performWithCurrentExampleGroup(group) {
|
||||
closure(context)
|
||||
}
|
||||
|
||||
group.walkDownExamples { (example: Example) in
|
||||
example.isSharedExample = true
|
||||
example.callsite = callsite
|
||||
}
|
||||
}
|
||||
|
||||
internal func fitBehavesLike<C>(_ behavior: Behavior<C>.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) {
|
||||
var focusedFlags = flags
|
||||
focusedFlags[Filter.focused] = true
|
||||
self.itBehavesLike(behavior, context: context, flags: focusedFlags, file: file, line: line)
|
||||
}
|
||||
|
||||
internal func xitBehavesLike<C>(_ behavior: Behavior<C>.Type, context: @escaping () -> C, flags: FilterFlags, file: String, line: UInt) {
|
||||
var pendingFlags = flags
|
||||
pendingFlags[Filter.pending] = true
|
||||
self.itBehavesLike(behavior, context: context, flags: pendingFlags, file: file, line: line)
|
||||
}
|
||||
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objc(itWithDescription:flags:file:line:closure:)
|
||||
private func objc_it(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
it(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(fitWithDescription:flags:file:line:closure:)
|
||||
private func objc_fit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
fit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(xitWithDescription:flags:file:line:closure:)
|
||||
private func objc_xit(_ description: String, flags: FilterFlags, file: String, line: UInt, closure: @escaping () -> Void) {
|
||||
xit(description, flags: flags, file: file, line: line, closure: closure)
|
||||
}
|
||||
|
||||
@objc(itBehavesLikeSharedExampleNamed:sharedExampleContext:flags:file:line:)
|
||||
private func objc_itBehavesLike(_ name: String, sharedExampleContext: @escaping SharedExampleContext, flags: FilterFlags, file: String, line: UInt) {
|
||||
itBehavesLike(name, sharedExampleContext: sharedExampleContext, flags: flags, file: file, line: line)
|
||||
}
|
||||
#endif
|
||||
|
||||
internal func pending(_ description: String, closure: () -> Void) {
|
||||
print("Pending: \(description)")
|
||||
}
|
||||
|
||||
private var currentPhase: String {
|
||||
if beforesCurrentlyExecuting {
|
||||
return "beforeEach"
|
||||
} else if aftersCurrentlyExecuting {
|
||||
return "afterEach"
|
||||
}
|
||||
|
||||
return "it"
|
||||
}
|
||||
}
|
||||
10
iOS/Example/Pods/Quick/Sources/Quick/ErrorUtility.swift
generated
Normal file
10
iOS/Example/Pods/Quick/Sources/Quick/ErrorUtility.swift
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
internal func raiseError(_ message: String) -> Never {
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise()
|
||||
#endif
|
||||
|
||||
// This won't be reached when ObjC is available and the exception above is raisd
|
||||
fatalError(message)
|
||||
}
|
||||
131
iOS/Example/Pods/Quick/Sources/Quick/Example.swift
generated
Normal file
131
iOS/Example/Pods/Quick/Sources/Quick/Example.swift
generated
Normal file
@@ -0,0 +1,131 @@
|
||||
import Foundation
|
||||
|
||||
private var numberOfExamplesRun = 0
|
||||
private var numberOfIncludedExamples = 0
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleBase: NSObject {}
|
||||
#endif
|
||||
#else
|
||||
public class _ExampleBase: NSObject {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Examples, defined with the `it` function, use assertions to
|
||||
demonstrate how code should behave. These are like "tests" in XCTest.
|
||||
*/
|
||||
final public class Example: _ExampleBase {
|
||||
/**
|
||||
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 internalDescription: String
|
||||
private let closure: () -> Void
|
||||
private let flags: FilterFlags
|
||||
|
||||
internal init(description: String, callsite: Callsite, flags: FilterFlags, closure: @escaping () -> Void) {
|
||||
self.internalDescription = description
|
||||
self.closure = closure
|
||||
self.callsite = callsite
|
||||
self.flags = flags
|
||||
}
|
||||
|
||||
public override var description: String {
|
||||
return internalDescription
|
||||
}
|
||||
|
||||
/**
|
||||
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 {
|
||||
guard let groupName = group?.name else { return description }
|
||||
return "\(groupName), \(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 numberOfIncludedExamples == 0 {
|
||||
numberOfIncludedExamples = world.includedExampleCount
|
||||
}
|
||||
|
||||
if numberOfExamplesRun == 0 {
|
||||
world.suiteHooks.executeBefores()
|
||||
}
|
||||
|
||||
let exampleMetadata = ExampleMetadata(example: self, exampleIndex: numberOfExamplesRun)
|
||||
world.currentExampleMetadata = exampleMetadata
|
||||
|
||||
world.exampleHooks.executeBefores(exampleMetadata)
|
||||
group!.phase = .beforesExecuting
|
||||
for before in group!.befores {
|
||||
before(exampleMetadata)
|
||||
}
|
||||
group!.phase = .beforesFinished
|
||||
|
||||
closure()
|
||||
|
||||
group!.phase = .aftersExecuting
|
||||
for after in group!.afters {
|
||||
after(exampleMetadata)
|
||||
}
|
||||
group!.phase = .aftersFinished
|
||||
world.exampleHooks.executeAfters(exampleMetadata)
|
||||
|
||||
numberOfExamplesRun += 1
|
||||
|
||||
if !world.isRunningAdditionalSuites && numberOfExamplesRun >= numberOfIncludedExamples {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
extension Example {
|
||||
/**
|
||||
Returns a boolean indicating whether two Example objects are equal.
|
||||
If two examples are defined at the exact same callsite, they must be equal.
|
||||
*/
|
||||
@nonobjc public static func == (lhs: Example, rhs: Example) -> Bool {
|
||||
return lhs.callsite == rhs.callsite
|
||||
}
|
||||
}
|
||||
99
iOS/Example/Pods/Quick/Sources/Quick/ExampleGroup.swift
generated
Normal file
99
iOS/Example/Pods/Quick/Sources/Quick/ExampleGroup.swift
generated
Normal file
@@ -0,0 +1,99 @@
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Example groups are logical groupings of examples, defined with
|
||||
the `describe` and `context` functions. Example groups can share
|
||||
setup and teardown code.
|
||||
*/
|
||||
final public class ExampleGroup: NSObject {
|
||||
weak internal var parent: ExampleGroup?
|
||||
internal let hooks = ExampleHooks()
|
||||
|
||||
internal var phase: HooksPhase = .nothingExecuted
|
||||
|
||||
private let internalDescription: 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.internalDescription = description
|
||||
self.flags = flags
|
||||
self.isInternalRootExampleGroup = isInternalRootExampleGroup
|
||||
}
|
||||
|
||||
public override var description: String {
|
||||
return internalDescription
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a list of examples that belong to this example group,
|
||||
or to any of its descendant example groups.
|
||||
*/
|
||||
public var examples: [Example] {
|
||||
return childExamples + childGroups.flatMap { $0.examples }
|
||||
}
|
||||
|
||||
internal var name: String? {
|
||||
guard let parent = parent else {
|
||||
return isInternalRootExampleGroup ? nil : description
|
||||
}
|
||||
|
||||
guard let name = parent.name else { return description }
|
||||
return "\(name), \(description)"
|
||||
}
|
||||
|
||||
internal var filterFlags: FilterFlags {
|
||||
var aggregateFlags = flags
|
||||
walkUp { group in
|
||||
for (key, value) in group.flags {
|
||||
aggregateFlags[key] = value
|
||||
}
|
||||
}
|
||||
return aggregateFlags
|
||||
}
|
||||
|
||||
internal var befores: [BeforeExampleWithMetadataClosure] {
|
||||
var closures = Array(hooks.befores.reversed())
|
||||
walkUp { group in
|
||||
closures.append(contentsOf: Array(group.hooks.befores.reversed()))
|
||||
}
|
||||
return Array(closures.reversed())
|
||||
}
|
||||
|
||||
internal var afters: [AfterExampleWithMetadataClosure] {
|
||||
var closures = hooks.afters
|
||||
walkUp { group in
|
||||
closures.append(contentsOf: group.hooks.afters)
|
||||
}
|
||||
return closures
|
||||
}
|
||||
|
||||
internal func walkDownExamples(_ callback: (_ example: Example) -> Void) {
|
||||
for example in childExamples {
|
||||
callback(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) -> Void) {
|
||||
var group = self
|
||||
while let parent = group.parent {
|
||||
callback(parent)
|
||||
group = parent
|
||||
}
|
||||
}
|
||||
}
|
||||
37
iOS/Example/Pods/Quick/Sources/Quick/ExampleMetadata.swift
generated
Normal file
37
iOS/Example/Pods/Quick/Sources/Quick/ExampleMetadata.swift
generated
Normal file
@@ -0,0 +1,37 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#else
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#endif
|
||||
#else
|
||||
public class _ExampleMetadataBase: NSObject {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
A class that encapsulates information about an example,
|
||||
including the index at which the example was executed, as
|
||||
well as the example itself.
|
||||
*/
|
||||
final public class ExampleMetadata: _ExampleMetadataBase {
|
||||
/**
|
||||
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
|
||||
}
|
||||
}
|
||||
44
iOS/Example/Pods/Quick/Sources/Quick/Filter.swift
generated
Normal file
44
iOS/Example/Pods/Quick/Sources/Quick/Filter.swift
generated
Normal file
@@ -0,0 +1,44 @@
|
||||
import Foundation
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
public class _FilterBase: NSObject {}
|
||||
#else
|
||||
public class _FilterBase: NSObject {}
|
||||
#endif
|
||||
#else
|
||||
public class _FilterBase: NSObject {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
final public class Filter: _FilterBase {
|
||||
/**
|
||||
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"
|
||||
}
|
||||
}
|
||||
35
iOS/Example/Pods/Quick/Sources/Quick/Hooks/Closures.swift
generated
Normal file
35
iOS/Example/Pods/Quick/Sources/Quick/Hooks/Closures.swift
generated
Normal file
@@ -0,0 +1,35 @@
|
||||
// MARK: Example Hooks
|
||||
|
||||
/**
|
||||
A closure executed before an example is run.
|
||||
*/
|
||||
public typealias BeforeExampleClosure = () -> Void
|
||||
|
||||
/**
|
||||
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) -> Void
|
||||
|
||||
/**
|
||||
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 = () -> Void
|
||||
|
||||
/**
|
||||
A closure executed after all examples have finished running.
|
||||
*/
|
||||
public typealias AfterSuiteClosure = BeforeSuiteClosure
|
||||
42
iOS/Example/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift
generated
Normal file
42
iOS/Example/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift
generated
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
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 var phase: HooksPhase = .nothingExecuted
|
||||
|
||||
internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) {
|
||||
befores.append(closure)
|
||||
}
|
||||
|
||||
internal func appendBefore(_ closure: @escaping BeforeExampleClosure) {
|
||||
befores.append { (_: ExampleMetadata) in closure() }
|
||||
}
|
||||
|
||||
internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) {
|
||||
afters.append(closure)
|
||||
}
|
||||
|
||||
internal func appendAfter(_ closure: @escaping AfterExampleClosure) {
|
||||
afters.append { (_: ExampleMetadata) in closure() }
|
||||
}
|
||||
|
||||
internal func executeBefores(_ exampleMetadata: ExampleMetadata) {
|
||||
phase = .beforesExecuting
|
||||
for before in befores {
|
||||
before(exampleMetadata)
|
||||
}
|
||||
|
||||
phase = .beforesFinished
|
||||
}
|
||||
|
||||
internal func executeAfters(_ exampleMetadata: ExampleMetadata) {
|
||||
phase = .aftersExecuting
|
||||
for after in afters {
|
||||
after(exampleMetadata)
|
||||
}
|
||||
|
||||
phase = .aftersFinished
|
||||
}
|
||||
}
|
||||
11
iOS/Example/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift
generated
Normal file
11
iOS/Example/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
A description of the execution cycle of the current example with
|
||||
respect to the hooks of that example.
|
||||
*/
|
||||
internal enum HooksPhase {
|
||||
case nothingExecuted
|
||||
case beforesExecuting
|
||||
case beforesFinished
|
||||
case aftersExecuting
|
||||
case aftersFinished
|
||||
}
|
||||
32
iOS/Example/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift
generated
Normal file
32
iOS/Example/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift
generated
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
A container for closures to be executed before and after all examples.
|
||||
*/
|
||||
final internal class SuiteHooks {
|
||||
internal var befores: [BeforeSuiteClosure] = []
|
||||
internal var afters: [AfterSuiteClosure] = []
|
||||
internal var phase: HooksPhase = .nothingExecuted
|
||||
|
||||
internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) {
|
||||
befores.append(closure)
|
||||
}
|
||||
|
||||
internal func appendAfter(_ closure: @escaping AfterSuiteClosure) {
|
||||
afters.append(closure)
|
||||
}
|
||||
|
||||
internal func executeBefores() {
|
||||
phase = .beforesExecuting
|
||||
for before in befores {
|
||||
before()
|
||||
}
|
||||
phase = .beforesFinished
|
||||
}
|
||||
|
||||
internal func executeAfters() {
|
||||
phase = .aftersExecuting
|
||||
for after in afters {
|
||||
after()
|
||||
}
|
||||
phase = .aftersFinished
|
||||
}
|
||||
}
|
||||
25
iOS/Example/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift
generated
Normal file
25
iOS/Example/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Bundle {
|
||||
|
||||
/**
|
||||
Locates the first bundle with a '.xctest' file extension.
|
||||
*/
|
||||
internal static var currentTestBundle: Bundle? {
|
||||
return allBundles.first { $0.bundlePath.hasSuffix(".xctest") }
|
||||
}
|
||||
|
||||
/**
|
||||
Return the module name of the bundle.
|
||||
Uses the bundle filename and transform it to match Xcode's transformation.
|
||||
Module name has to be a valid "C99 extended identifier".
|
||||
*/
|
||||
internal var moduleName: String {
|
||||
let fileName = bundleURL.fileName as NSString
|
||||
return fileName.c99ExtendedIdentifier
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
33
iOS/Example/Pods/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift
generated
Normal file
33
iOS/Example/Pods/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
import Foundation
|
||||
|
||||
public extension NSString {
|
||||
|
||||
private static var invalidCharacters: CharacterSet = {
|
||||
var invalidCharacters = CharacterSet()
|
||||
|
||||
let invalidCharacterSets: [CharacterSet] = [
|
||||
.whitespacesAndNewlines,
|
||||
.illegalCharacters,
|
||||
.controlCharacters,
|
||||
.punctuationCharacters,
|
||||
.nonBaseCharacters,
|
||||
.symbols
|
||||
]
|
||||
|
||||
for invalidSet in invalidCharacterSets {
|
||||
invalidCharacters.formUnion(invalidSet)
|
||||
}
|
||||
|
||||
return invalidCharacters
|
||||
}()
|
||||
|
||||
@objc(qck_c99ExtendedIdentifier)
|
||||
var c99ExtendedIdentifier: String {
|
||||
let validComponents = components(separatedBy: NSString.invalidCharacters)
|
||||
let result = validComponents.joined(separator: "_")
|
||||
|
||||
return result.isEmpty ? "_" : result
|
||||
}
|
||||
}
|
||||
#endif
|
||||
74
iOS/Example/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift
generated
Normal file
74
iOS/Example/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift
generated
Normal file
@@ -0,0 +1,74 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Responsible for building a "Selected tests" suite. This corresponds to a single
|
||||
spec, and all its examples.
|
||||
*/
|
||||
internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder {
|
||||
|
||||
/**
|
||||
The test spec class to run.
|
||||
*/
|
||||
let testCaseClass: AnyClass!
|
||||
|
||||
/**
|
||||
For Objective-C classes, returns the class name. For Swift classes without,
|
||||
an explicit Objective-C name, returns a module-namespaced class name
|
||||
(e.g., "FooTests.FooSpec").
|
||||
*/
|
||||
var testSuiteClassName: String {
|
||||
return NSStringFromClass(testCaseClass)
|
||||
}
|
||||
|
||||
/**
|
||||
Given a test case name:
|
||||
|
||||
FooSpec/testFoo
|
||||
|
||||
Optionally constructs a test suite builder for the named test case class
|
||||
in the running test bundle.
|
||||
|
||||
If no test bundle can be found, or the test case class can't be found,
|
||||
initialization fails and returns `nil`.
|
||||
*/
|
||||
init?(forTestCaseWithName name: String) {
|
||||
guard let testCaseClass = testCaseClassForTestCaseWithName(name) else {
|
||||
self.testCaseClass = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
self.testCaseClass = testCaseClass
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a `QuickTestSuite` that runs the associated test case class.
|
||||
*/
|
||||
func buildTestSuite() -> QuickTestSuite {
|
||||
return QuickTestSuite(forTestCaseClass: testCaseClass)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named
|
||||
test case class in that bundle.
|
||||
|
||||
Returns `nil` if a bundle or test case class cannot be found.
|
||||
*/
|
||||
private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? {
|
||||
func extractClassName(_ name: String) -> String? {
|
||||
return name.components(separatedBy: "/").first
|
||||
}
|
||||
|
||||
guard let className = extractClassName(name) else { return nil }
|
||||
guard let bundle = Bundle.currentTestBundle else { return nil }
|
||||
|
||||
if let testCaseClass = bundle.classNamed(className) { return testCaseClass }
|
||||
|
||||
let moduleName = bundle.moduleName
|
||||
|
||||
return NSClassFromString("\(moduleName).\(className)")
|
||||
}
|
||||
|
||||
#endif
|
||||
52
iOS/Example/Pods/Quick/Sources/Quick/QuickTestSuite.swift
generated
Normal file
52
iOS/Example/Pods/Quick/Sources/Quick/QuickTestSuite.swift
generated
Normal file
@@ -0,0 +1,52 @@
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
|
||||
import XCTest
|
||||
|
||||
/**
|
||||
This protocol defines the role of an object that builds test suites.
|
||||
*/
|
||||
internal protocol QuickTestSuiteBuilder {
|
||||
|
||||
/**
|
||||
Construct a `QuickTestSuite` instance with the appropriate test cases added as tests.
|
||||
|
||||
Subsequent calls to this method should return equivalent test suites.
|
||||
*/
|
||||
func buildTestSuite() -> QuickTestSuite
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
A base class for a class cluster of Quick test suites, that should correctly
|
||||
build dynamic test suites for XCTest to execute.
|
||||
*/
|
||||
public class QuickTestSuite: XCTestSuite {
|
||||
|
||||
private static var builtTestSuites: Set<String> = Set()
|
||||
|
||||
/**
|
||||
Construct a test suite for a specific, selected subset of test cases (rather
|
||||
than the default, which as all test cases).
|
||||
|
||||
If this method is called multiple times for the same test case class, e.g..
|
||||
|
||||
FooSpec/testFoo
|
||||
FooSpec/testBar
|
||||
|
||||
It is expected that the first call should return a valid test suite, and
|
||||
all subsequent calls should return `nil`.
|
||||
*/
|
||||
@objc
|
||||
public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? {
|
||||
guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil }
|
||||
|
||||
let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName)
|
||||
if inserted {
|
||||
return builder.buildTestSuite()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
12
iOS/Example/Pods/Quick/Sources/Quick/URL+FileName.swift
generated
Normal file
12
iOS/Example/Pods/Quick/Sources/Quick/URL+FileName.swift
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
import Foundation
|
||||
|
||||
extension URL {
|
||||
|
||||
/**
|
||||
Returns the path file name without file extension.
|
||||
*/
|
||||
var fileName: String {
|
||||
return self.deletingPathExtension().lastPathComponent
|
||||
}
|
||||
|
||||
}
|
||||
247
iOS/Example/Pods/Quick/Sources/Quick/World.swift
generated
Normal file
247
iOS/Example/Pods/Quick/Sources/Quick/World.swift
generated
Normal file
@@ -0,0 +1,247 @@
|
||||
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 = () -> [String: Any]
|
||||
|
||||
/**
|
||||
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 = (@escaping SharedExampleContext) -> Void
|
||||
|
||||
// `#if swift(>=3.2) && (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE`
|
||||
// does not work as expected.
|
||||
#if swift(>=3.2)
|
||||
#if (os(macOS) || os(iOS) || os(tvOS) || os(watchOS)) && !SWIFT_PACKAGE
|
||||
@objcMembers
|
||||
internal class _WorldBase: NSObject {}
|
||||
#else
|
||||
internal class _WorldBase: NSObject {}
|
||||
#endif
|
||||
#else
|
||||
internal class _WorldBase: NSObject {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
final internal class World: _WorldBase {
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
internal 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.
|
||||
*/
|
||||
|
||||
internal 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.
|
||||
*/
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
// Convention of generating Objective-C selector has been changed on Swift 3
|
||||
@objc(isRunningAdditionalSuites)
|
||||
internal var isRunningAdditionalSuites = false
|
||||
#else
|
||||
internal var isRunningAdditionalSuites = false
|
||||
#endif
|
||||
|
||||
private var specs: [String: ExampleGroup] = [:]
|
||||
private var sharedExamples: [String: SharedExampleClosure] = [:]
|
||||
private let configuration = Configuration()
|
||||
|
||||
internal private(set) var isConfigurationFinalized = false
|
||||
|
||||
internal var exampleHooks: ExampleHooks {return configuration.exampleHooks }
|
||||
internal var suiteHooks: SuiteHooks { return configuration.suiteHooks }
|
||||
|
||||
// MARK: Singleton Constructor
|
||||
|
||||
private override init() {}
|
||||
|
||||
static let sharedWorld = World()
|
||||
|
||||
// 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.
|
||||
|
||||
- parameter closure: A closure that takes a Configuration object that can
|
||||
be mutated to change Quick's behavior.
|
||||
*/
|
||||
internal 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)
|
||||
}
|
||||
|
||||
/**
|
||||
Finalizes the World's configuration.
|
||||
Any subsequent calls to World.configure() will raise.
|
||||
*/
|
||||
internal 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") {}
|
||||
}
|
||||
|
||||
- parameter cls: The QuickSpec class for which to retrieve the root example group.
|
||||
- returns: The root example group for the class.
|
||||
*/
|
||||
internal func rootExampleGroupForSpecClass(_ cls: AnyClass) -> ExampleGroup {
|
||||
let name = String(describing: 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.
|
||||
|
||||
- parameter specClass: The QuickSpec subclass for which examples are to be returned.
|
||||
- returns: A list of examples to be run as test invocations.
|
||||
*/
|
||||
internal 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 { included.contains($0) }
|
||||
// 3. Remove all excluded examples.
|
||||
return spec.filter { example in
|
||||
!self.configuration.exclusionFilters.reduce(false) { $0 || $1(example) }
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
@objc(examplesForSpecClass:)
|
||||
private func objc_examples(_ specClass: AnyClass) -> [Example] {
|
||||
return examples(specClass)
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal func registerSharedExample(_ name: String, closure: @escaping SharedExampleClosure) {
|
||||
raiseIfSharedExampleAlreadyRegistered(name)
|
||||
sharedExamples[name] = closure
|
||||
}
|
||||
|
||||
internal func sharedExample(_ name: String) -> SharedExampleClosure {
|
||||
raiseIfSharedExampleNotRegistered(name)
|
||||
return sharedExamples[name]!
|
||||
}
|
||||
|
||||
internal var includedExampleCount: Int {
|
||||
return includedExamples.count
|
||||
}
|
||||
|
||||
internal var beforesCurrentlyExecuting: Bool {
|
||||
let suiteBeforesExecuting = suiteHooks.phase == .beforesExecuting
|
||||
let exampleBeforesExecuting = exampleHooks.phase == .beforesExecuting
|
||||
var groupBeforesExecuting = false
|
||||
if let runningExampleGroup = currentExampleMetadata?.example.group {
|
||||
groupBeforesExecuting = runningExampleGroup.phase == .beforesExecuting
|
||||
}
|
||||
|
||||
return suiteBeforesExecuting || exampleBeforesExecuting || groupBeforesExecuting
|
||||
}
|
||||
|
||||
internal var aftersCurrentlyExecuting: Bool {
|
||||
let suiteAftersExecuting = suiteHooks.phase == .aftersExecuting
|
||||
let exampleAftersExecuting = exampleHooks.phase == .aftersExecuting
|
||||
var groupAftersExecuting = false
|
||||
if let runningExampleGroup = currentExampleMetadata?.example.group {
|
||||
groupAftersExecuting = runningExampleGroup.phase == .aftersExecuting
|
||||
}
|
||||
|
||||
return suiteAftersExecuting || exampleAftersExecuting || groupAftersExecuting
|
||||
}
|
||||
|
||||
internal func performWithCurrentExampleGroup(_ group: ExampleGroup, closure: () -> Void) {
|
||||
let previousExampleGroup = currentExampleGroup
|
||||
currentExampleGroup = group
|
||||
|
||||
closure()
|
||||
|
||||
currentExampleGroup = previousExampleGroup
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
if included.isEmpty && configuration.runAllWhenEverythingFiltered {
|
||||
return all
|
||||
} else {
|
||||
return included
|
||||
}
|
||||
}
|
||||
|
||||
private func raiseIfSharedExampleAlreadyRegistered(_ name: String) {
|
||||
if sharedExamples[name] != nil {
|
||||
raiseError("A shared example named '\(name)' has already been registered.")
|
||||
}
|
||||
}
|
||||
|
||||
private func raiseIfSharedExampleNotRegistered(_ name: String) {
|
||||
if sharedExamples[name] == nil {
|
||||
raiseError("No shared example named '\(name)' has been registered. Registered shared examples: '\(Array(sharedExamples.keys))'")
|
||||
}
|
||||
}
|
||||
}
|
||||
30
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h
generated
Normal file
30
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class Configuration;
|
||||
|
||||
/**
|
||||
Subclass QuickConfiguration and override the +[QuickConfiguration configure:]
|
||||
method in order to configure how Quick behaves when running specs, or to define
|
||||
shared examples that are used across spec files.
|
||||
*/
|
||||
@interface QuickConfiguration : NSObject
|
||||
|
||||
/**
|
||||
This method is executed on each subclass of this class before Quick runs
|
||||
any examples. You may override this method on as many subclasses as you like, but
|
||||
there is no guarantee as to the order in which these methods are executed.
|
||||
|
||||
You can override this method in order to:
|
||||
|
||||
1. Configure how Quick behaves, by modifying properties on the Configuration object.
|
||||
Setting the same properties in several methods has undefined behavior.
|
||||
|
||||
2. Define shared examples using `sharedExamples`.
|
||||
|
||||
@param configuration A mutable object that is used to configure how Quick behaves on
|
||||
a framework level. For details on all the options, see the
|
||||
documentation in Configuration.swift.
|
||||
*/
|
||||
+ (void)configure:(Configuration *)configuration;
|
||||
|
||||
@end
|
||||
83
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m
generated
Normal file
83
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
#import "QuickConfiguration.h"
|
||||
#import "World.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
|
||||
234
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h
generated
Normal file
234
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h
generated
Normal file
@@ -0,0 +1,234 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class ExampleMetadata;
|
||||
|
||||
/**
|
||||
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);
|
||||
typedef void (^QCKDSLExampleMetadataBlock)(ExampleMetadata *exampleMetadata);
|
||||
|
||||
#define QUICK_EXPORT FOUNDATION_EXPORT
|
||||
|
||||
QUICK_EXPORT void qck_beforeSuite(QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_afterSuite(QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure);
|
||||
QUICK_EXPORT void qck_describe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_context(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_beforeEach(QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure);
|
||||
QUICK_EXPORT void qck_afterEach(QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure);
|
||||
QUICK_EXPORT void qck_pending(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure);
|
||||
QUICK_EXPORT 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);
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to QCKDSL.beforeEach, except the closure is provided with
|
||||
metadata on the example that the closure is being run prior to.
|
||||
*/
|
||||
static inline void beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
|
||||
qck_beforeEachWithMetadata(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);
|
||||
}
|
||||
|
||||
/**
|
||||
Identical to QCKDSL.afterEach, except the closure is provided with
|
||||
metadata on the example that the closure is being run after.
|
||||
*/
|
||||
static inline void afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
|
||||
qck_afterEachWithMetadata(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);
|
||||
|
||||
QUICK_EXPORT QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line);
|
||||
QUICK_EXPORT QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line);
|
||||
79
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m
generated
Normal file
79
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
#import "QCKDSL.h"
|
||||
#import "World.h"
|
||||
#import "World+DSL.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 flags:@{} closure:closure];
|
||||
}
|
||||
|
||||
void qck_context(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_describe(description, closure);
|
||||
}
|
||||
|
||||
void qck_beforeEach(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] beforeEach:closure];
|
||||
}
|
||||
|
||||
void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
|
||||
[[World sharedWorld] beforeEachWithMetadata:closure];
|
||||
}
|
||||
|
||||
void qck_afterEach(QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] afterEach:closure];
|
||||
}
|
||||
|
||||
void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
|
||||
[[World sharedWorld] afterEachWithMetadata: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 flags:@{} closure:closure];
|
||||
}
|
||||
|
||||
void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_xdescribe(description, closure);
|
||||
}
|
||||
|
||||
void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
[[World sharedWorld] fdescribe:description flags:@{} closure:closure];
|
||||
}
|
||||
|
||||
void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) {
|
||||
qck_fdescribe(description, closure);
|
||||
}
|
||||
20
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h
generated
Normal file
20
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
@interface World (SWIFT_EXTENSION(Quick))
|
||||
- (void)beforeSuite:(void (^ __nonnull)(void))closure;
|
||||
- (void)afterSuite:(void (^ __nonnull)(void))closure;
|
||||
- (void)sharedExamples:(NSString * __nonnull)name closure:(void (^ __nonnull)(NSDictionary * __nonnull (^ __nonnull)(void)))closure;
|
||||
- (void)describe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)context:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)fdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)xdescribe:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)beforeEach:(void (^ __nonnull)(void))closure;
|
||||
- (void)beforeEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure;
|
||||
- (void)afterEach:(void (^ __nonnull)(void))closure;
|
||||
- (void)afterEachWithMetadata:(void (^ __nonnull)(ExampleMetadata * __nonnull))closure;
|
||||
- (void)itWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)fitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)xitWithDescription:(NSString * __nonnull)description flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line closure:(void (^ __nonnull)(void))closure;
|
||||
- (void)itBehavesLikeSharedExampleNamed:(NSString * __nonnull)name sharedExampleContext:(NSDictionary * __nonnull (^ __nonnull)(void))sharedExampleContext flags:(NSDictionary * __nonnull)flags file:(NSString * __nonnull)file line:(NSUInteger)line;
|
||||
- (void)pending:(NSString * __nonnull)description closure:(void (^ __nonnull)(void))closure;
|
||||
@end
|
||||
11
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Quick.h
generated
Normal file
11
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/Quick.h
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for Quick.
|
||||
FOUNDATION_EXPORT double QuickVersionNumber;
|
||||
|
||||
//! Project version string for Quick.
|
||||
FOUNDATION_EXPORT const unsigned char QuickVersionString[];
|
||||
|
||||
#import "QuickSpec.h"
|
||||
#import "QCKDSL.h"
|
||||
#import "QuickConfiguration.h"
|
||||
50
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h
generated
Normal file
50
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h
generated
Normal file
@@ -0,0 +1,50 @@
|
||||
#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.
|
||||
|
||||
@code
|
||||
override func spec() {
|
||||
describe("winter") {
|
||||
it("is coming") {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
See DSL.swift for more information on what syntax is available.
|
||||
*/
|
||||
- (void)spec;
|
||||
|
||||
@end
|
||||
141
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.m
generated
Normal file
141
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.m
generated
Normal file
@@ -0,0 +1,141 @@
|
||||
#import "QuickSpec.h"
|
||||
#import "QuickConfiguration.h"
|
||||
#import "World.h"
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
static QuickSpec *currentSpec = nil;
|
||||
|
||||
@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 performWithCurrentExampleGroup:[world rootExampleGroupForSpecClass:self] closure:^{
|
||||
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];
|
||||
}
|
||||
[self testInvocations];
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
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]];
|
||||
|
||||
NSMutableSet<NSString*> *selectorNames = [NSMutableSet set];
|
||||
|
||||
for (Example *example in examples) {
|
||||
SEL selector = [self addInstanceMethodForExample:example classSelectorNames:selectorNames];
|
||||
|
||||
NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
invocation.selector = selector;
|
||||
|
||||
[invocations addObject:invocation];
|
||||
}
|
||||
|
||||
return invocations;
|
||||
}
|
||||
|
||||
#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 classSelectorNames:(NSMutableSet<NSString*> *)selectorNames {
|
||||
IMP implementation = imp_implementationWithBlock(^(QuickSpec *self){
|
||||
self.example = example;
|
||||
currentSpec = self;
|
||||
[example run];
|
||||
});
|
||||
|
||||
const char *types = [[NSString stringWithFormat:@"%s%s%s", @encode(void), @encode(id), @encode(SEL)] UTF8String];
|
||||
|
||||
NSString *originalName = example.name.qck_c99ExtendedIdentifier;
|
||||
NSString *selectorName = originalName;
|
||||
NSUInteger i = 2;
|
||||
|
||||
while ([selectorNames containsObject:selectorName]) {
|
||||
selectorName = [NSString stringWithFormat:@"%@_%tu", originalName, i++];
|
||||
}
|
||||
|
||||
[selectorNames addObject:selectorName];
|
||||
|
||||
SEL selector = NSSelectorFromString(selectorName);
|
||||
class_addMethod(self, selector, implementation, types);
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
[currentSpec.testRun recordFailureWithDescription:description
|
||||
inFile:filePath
|
||||
atLine:lineNumber
|
||||
expected:expected];
|
||||
}
|
||||
|
||||
@end
|
||||
18
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/World.h
generated
Normal file
18
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/World.h
generated
Normal file
@@ -0,0 +1,18 @@
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
@class ExampleGroup;
|
||||
@class ExampleMetadata;
|
||||
|
||||
SWIFT_CLASS("_TtC5Quick5World")
|
||||
@interface World
|
||||
|
||||
@property (nonatomic) ExampleGroup * __nullable currentExampleGroup;
|
||||
@property (nonatomic) ExampleMetadata * __nullable currentExampleMetadata;
|
||||
@property (nonatomic) BOOL isRunningAdditionalSuites;
|
||||
+ (World * __nonnull)sharedWorld;
|
||||
- (void)configure:(void (^ __nonnull)(Configuration * __nonnull))closure;
|
||||
- (void)finalizeConfiguration;
|
||||
- (ExampleGroup * __nonnull)rootExampleGroupForSpecClass:(Class __nonnull)cls;
|
||||
- (NSArray * __nonnull)examplesForSpecClass:(Class __nonnull)specClass;
|
||||
- (void)performWithCurrentExampleGroup:(ExampleGroup * __nonnull)group closure:(void (^ __nonnull)(void))closure;
|
||||
@end
|
||||
40
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m
generated
Normal file
40
iOS/Example/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m
generated
Normal file
@@ -0,0 +1,40 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <Quick/Quick-Swift.h>
|
||||
|
||||
@interface XCTestSuite (QuickTestSuiteBuilder)
|
||||
@end
|
||||
|
||||
@implementation XCTestSuite (QuickTestSuiteBuilder)
|
||||
|
||||
/**
|
||||
In order to ensure we can correctly build dynamic test suites, we need to
|
||||
replace some of the default test suite constructors.
|
||||
*/
|
||||
+ (void)load {
|
||||
Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:));
|
||||
Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:));
|
||||
method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName);
|
||||
}
|
||||
|
||||
/**
|
||||
The `+testSuiteForTestCaseWithName:` method is called when a specific test case
|
||||
class is run from the Xcode test navigator. If the built test suite is `nil`,
|
||||
Xcode will not run any tests for that test case.
|
||||
|
||||
Given if the following test case class is run from the Xcode test navigator:
|
||||
|
||||
FooSpec
|
||||
testFoo
|
||||
testBar
|
||||
|
||||
XCTest will invoke this once per test case, with test case names following this format:
|
||||
|
||||
FooSpec/testFoo
|
||||
FooSpec/testBar
|
||||
*/
|
||||
+ (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name {
|
||||
return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name];
|
||||
}
|
||||
|
||||
@end
|
||||
55
iOS/Example/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m
generated
Normal file
55
iOS/Example/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m
generated
Normal file
@@ -0,0 +1,55 @@
|
||||
#import "QuickSpecBase.h"
|
||||
|
||||
#pragma mark - _QuickSelectorWrapper
|
||||
|
||||
@interface _QuickSelectorWrapper ()
|
||||
@property(nonatomic, assign) SEL selector;
|
||||
@end
|
||||
|
||||
@implementation _QuickSelectorWrapper
|
||||
|
||||
- (instancetype)initWithSelector:(SEL)selector {
|
||||
self = [super init];
|
||||
_selector = selector;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - _QuickSpecBase
|
||||
|
||||
@implementation _QuickSpecBase
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super initWithInvocation: nil];
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
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<NSInvocation *> *)testInvocations {
|
||||
NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors];
|
||||
NSMutableArray<NSInvocation *> *invocations = [NSMutableArray arrayWithCapacity:wrappers.count];
|
||||
|
||||
for (_QuickSelectorWrapper *wrapper in wrappers) {
|
||||
SEL selector = wrapper.selector;
|
||||
NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
invocation.selector = selector;
|
||||
|
||||
[invocations addObject:invocation];
|
||||
}
|
||||
|
||||
return invocations;
|
||||
}
|
||||
|
||||
+ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors {
|
||||
return @[];
|
||||
}
|
||||
|
||||
@end
|
||||
11
iOS/Example/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h
generated
Normal file
11
iOS/Example/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface _QuickSelectorWrapper : NSObject
|
||||
- (instancetype)initWithSelector:(SEL)selector;
|
||||
@end
|
||||
|
||||
@interface _QuickSpecBase : XCTestCase
|
||||
+ (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors;
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
@end
|
||||
Reference in New Issue
Block a user