├── .codecov.yml
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .swiftlint.yml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── .travis.yml
├── CONTRIBUTING.md
├── Example
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
├── Base.lproj
│ └── LaunchScreen.storyboard
├── DemoViewController.swift
├── Extensions
│ ├── UIColor+Extensions.swift
│ └── UIView+Extensions.swift
├── LanguageExample
│ ├── CodingLanguage.swift
│ ├── LanguageExample.storyboard
│ ├── LanguageExampleProgressView.swift
│ └── LanguageExampleViewController.swift
├── MultiProgressViewExample.plist
└── StorageExample
│ ├── StorageExampleViewController.swift
│ ├── StorageProgressSection.swift
│ ├── StorageStackView.swift
│ └── StorageType.swift
├── Images
├── example1.gif
├── example2.gif
├── header.png
├── social_preview.png
├── storyboard_data_source.gif
├── storyboard_ib_outlet.gif
└── storyboard_identity_inspector.gif
├── LICENSE
├── MultiProgressView.podspec
├── MultiProgressView.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ ├── IDETemplateMacros.plist
│ └── xcschemes
│ └── MultiProgressView.xcscheme
├── MultiProgressView.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── WorkspaceSettings.xcsettings
├── Package.resolved
├── Package.swift
├── Podfile
├── Podfile.lock
├── Pods
├── Manifest.lock
├── Nimble
│ ├── Carthage
│ │ └── Checkouts
│ │ │ ├── CwlCatchException
│ │ │ └── Sources
│ │ │ │ ├── CwlCatchException
│ │ │ │ └── CwlCatchException.swift
│ │ │ │ └── CwlCatchExceptionSupport
│ │ │ │ ├── CwlCatchException.m
│ │ │ │ └── include
│ │ │ │ └── CwlCatchException.h
│ │ │ └── CwlPreconditionTesting
│ │ │ └── Sources
│ │ │ ├── CwlMachBadInstructionHandler
│ │ │ ├── CwlMachBadInstructionHandler.m
│ │ │ ├── include
│ │ │ │ └── CwlMachBadInstructionHandler.h
│ │ │ ├── mach_excServer.c
│ │ │ └── mach_excServer.h
│ │ │ └── CwlPreconditionTesting
│ │ │ ├── CwlBadInstructionException.swift
│ │ │ ├── CwlCatchBadInstruction.swift
│ │ │ ├── CwlDarwinDefinitions.swift
│ │ │ └── Mach
│ │ │ └── CwlPreconditionTesting.h
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ │ ├── Nimble
│ │ ├── Adapters
│ │ │ ├── AdapterProtocols.swift
│ │ │ ├── AssertionDispatcher.swift
│ │ │ ├── AssertionRecorder.swift
│ │ │ ├── NMBExpectation.swift
│ │ │ ├── NMBObjCMatcher.swift
│ │ │ ├── NimbleEnvironment.swift
│ │ │ └── NimbleXCTestHandler.swift
│ │ ├── DSL+Wait.swift
│ │ ├── DSL.swift
│ │ ├── Expectation.swift
│ │ ├── ExpectationMessage.swift
│ │ ├── Expression.swift
│ │ ├── FailureMessage.swift
│ │ ├── Matchers
│ │ │ ├── AllPass.swift
│ │ │ ├── Async.swift
│ │ │ ├── BeAKindOf.swift
│ │ │ ├── BeAnInstanceOf.swift
│ │ │ ├── BeCloseTo.swift
│ │ │ ├── BeEmpty.swift
│ │ │ ├── BeGreaterThan.swift
│ │ │ ├── BeGreaterThanOrEqualTo.swift
│ │ │ ├── BeIdenticalTo.swift
│ │ │ ├── BeLessThan.swift
│ │ │ ├── BeLessThanOrEqual.swift
│ │ │ ├── BeLogical.swift
│ │ │ ├── BeNil.swift
│ │ │ ├── BeVoid.swift
│ │ │ ├── BeginWith.swift
│ │ │ ├── Contain.swift
│ │ │ ├── ContainElementSatisfying.swift
│ │ │ ├── ElementsEqual.swift
│ │ │ ├── EndWith.swift
│ │ │ ├── Equal.swift
│ │ │ ├── HaveCount.swift
│ │ │ ├── Match.swift
│ │ │ ├── MatchError.swift
│ │ │ ├── MatcherFunc.swift
│ │ │ ├── MatcherProtocols.swift
│ │ │ ├── PostNotification.swift
│ │ │ ├── Predicate.swift
│ │ │ ├── RaisesException.swift
│ │ │ ├── SatisfyAllOf.swift
│ │ │ ├── SatisfyAnyOf.swift
│ │ │ ├── ThrowAssertion.swift
│ │ │ ├── ThrowError.swift
│ │ │ └── ToSucceed.swift
│ │ ├── Nimble.h
│ │ └── Utils
│ │ │ ├── Await.swift
│ │ │ ├── Errors.swift
│ │ │ ├── Functional.swift
│ │ │ ├── SourceLocation.swift
│ │ │ └── Stringers.swift
│ │ └── NimbleObjectiveC
│ │ ├── DSL.h
│ │ ├── DSL.m
│ │ ├── NMBExceptionCapture.h
│ │ ├── NMBExceptionCapture.m
│ │ ├── NMBStringify.h
│ │ ├── NMBStringify.m
│ │ └── XCTestObservationCenter+Register.m
├── Pods.xcodeproj
│ └── project.pbxproj
├── Quick
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ │ ├── Quick
│ │ ├── Behavior.swift
│ │ ├── Callsite.swift
│ │ ├── Configuration
│ │ │ └── Configuration.swift
│ │ ├── DSL
│ │ │ ├── DSL.swift
│ │ │ └── World+DSL.swift
│ │ ├── ErrorUtility.swift
│ │ ├── Example.swift
│ │ ├── ExampleGroup.swift
│ │ ├── ExampleMetadata.swift
│ │ ├── Filter.swift
│ │ ├── Hooks
│ │ │ ├── Closures.swift
│ │ │ ├── ExampleHooks.swift
│ │ │ ├── HooksPhase.swift
│ │ │ └── SuiteHooks.swift
│ │ ├── NSBundle+CurrentTestBundle.swift
│ │ ├── QuickSelectedTestSuiteBuilder.swift
│ │ ├── QuickTestSuite.swift
│ │ ├── String+C99ExtendedIdentifier.swift
│ │ ├── URL+FileName.swift
│ │ └── World.swift
│ │ ├── QuickObjectiveC
│ │ ├── Configuration
│ │ │ ├── QuickConfiguration.h
│ │ │ └── QuickConfiguration.m
│ │ ├── DSL
│ │ │ ├── QCKDSL.h
│ │ │ └── QCKDSL.m
│ │ ├── Quick.h
│ │ ├── QuickSpec.h
│ │ ├── QuickSpec.m
│ │ └── XCTestSuite+QuickTestSuiteBuilder.m
│ │ └── QuickSpecBase
│ │ ├── QuickSpecBase.m
│ │ └── include
│ │ └── QuickSpecBase.h
└── Target Support Files
│ ├── Nimble
│ ├── Nimble-Info.plist
│ ├── Nimble-dummy.m
│ ├── Nimble-prefix.pch
│ ├── Nimble-umbrella.h
│ ├── Nimble.modulemap
│ └── Nimble.xcconfig
│ ├── Pods-MultiProgressViewTests
│ ├── Pods-MultiProgressViewTests-Info.plist
│ ├── Pods-MultiProgressViewTests-acknowledgements.markdown
│ ├── Pods-MultiProgressViewTests-acknowledgements.plist
│ ├── Pods-MultiProgressViewTests-dummy.m
│ ├── Pods-MultiProgressViewTests-frameworks.sh
│ ├── Pods-MultiProgressViewTests-umbrella.h
│ ├── Pods-MultiProgressViewTests.debug.xcconfig
│ ├── Pods-MultiProgressViewTests.modulemap
│ └── Pods-MultiProgressViewTests.release.xcconfig
│ └── Quick
│ ├── Quick-Info.plist
│ ├── Quick-dummy.m
│ ├── Quick-prefix.pch
│ ├── Quick-umbrella.h
│ ├── Quick.modulemap
│ └── Quick.xcconfig
├── README.md
├── Sources
├── MultiProgressView.h
├── MultiProgressView.plist
└── MultiProgressView
│ ├── AlignmentType.swift
│ ├── Internal
│ └── TapGestureRecognizer.swift
│ ├── LayoutProvider.swift
│ ├── LineCapType.swift
│ ├── MultiProgressView.swift
│ └── ProgressViewSection.swift
└── Tests
├── MultiProgressViewTests.plist
└── MultiProgressViewTests
├── Mocks
├── MockLayoutProvider.swift
├── MockMultiProgressViewDataSource.swift
├── MockProgressViewDelegate.swift
└── MockProgressViewSectionDelegate.swift
├── NSLayoutConstraint+TestHelpers.swift
├── Specs
├── LayoutProviderSpec.swift
├── MultiProgressViewSpec.swift
└── ProgressViewSectionSpec.swift
└── Testables
├── TestableMultiProgressView.swift
└── TestableProgressViewSection.swift
/.codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | require_ci_to_pass: yes
4 |
5 | coverage:
6 | precision: 1 # number of decimal places
7 | round: down # round down coverage
8 | range: "70...100" # visual color range in codecov
9 | status:
10 | project: yes # measures the overall project coverage and compares it against the base of the pull request or parent commit
11 | patch: # measures only the lines adjusted in the pull request or single commit, if the commit is not in a pull request
12 | default:
13 | target: 100% # all new code should have 100% coverage
14 | changes: yes # detect changes in coverage that are NOT included in the commit/pull diff, and report these changes as a commit status
15 |
16 | parsers:
17 | gcov:
18 | branch_detection:
19 | conditional: yes
20 | loop: yes
21 | method: no
22 | macro: no
23 |
24 | comment: # configure github pull request comment
25 | layout: "diff, flags, files"
26 | behavior: default # update comment, if exists. Otherwise post new.
27 | require_changes: no # comments post regardless if there is a coverage change or not
28 |
29 | ignore: # ignore these files when measuring absolute coverage (reported in the Github badge)
30 | - "Pods/"
31 | - "Sources/MultiProgressView/Internal"
32 | - "Tests/"
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project-wide
2 | .DS_Store
3 |
4 | # Xcode
5 |
6 | ## User settings
7 | xcuserdata/
8 |
9 | ## Obj-C/Swift specific
10 | *.hmap
11 |
12 | # Swift Package Manager
13 | #
14 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
15 | # Packages/
16 | # Package.pins
17 | # Package.resolved
18 | # *.xcodeproj
19 | #
20 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
21 | # hence it is not needed unless you have added a package configuration file to your project
22 | .swiftpm/
23 |
24 | .build/
25 |
26 | # CocoaPods
27 | #
28 | # We recommend against adding the Pods directory to your .gitignore. However
29 | # you should judge for yourself, the pros and cons are mentioned at:
30 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
31 | #
32 | # Pods/
33 | #
34 | # Add this line if you want to avoid checking in source code from the Xcode workspace
35 | # *.xcworkspace
36 |
37 | # Carthage
38 | #
39 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
40 | # Carthage/Checkouts
41 |
42 | Carthage/Build/
43 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included: # paths to include during linting. `--path` is ignored if present.
2 | - Example
3 | - Sources
4 | - Tests
5 |
6 | disabled_rules: # rule identifiers to exclude from running
7 | - orphaned_doc_comment
8 | - type_name
9 |
10 | opt_in_rules: # some rules are only opt-in
11 | - anyobject_protocol
12 | - attributes
13 | - class_delegate_protocol
14 | - closure_body_length
15 | - closure_end_indentation
16 | - closure_spacing
17 | - convenience_type
18 | - discouraged_object_literal
19 | - discouraged_optional_collection
20 | - empty_collection_literal
21 | - empty_count
22 | - empty_string
23 | - empty_xctest_method
24 | - explicit_init
25 | - extension_access_modifier
26 | - fatal_error_message
27 | - file_name
28 | - file_name_no_space
29 | - flatmap_over_map_reduce
30 | - force_unwrapping
31 | - identical_operands
32 | - implicitly_unwrapped_optional
33 | - joined_default_parameter
34 | - last_where
35 | - legacy_multiple
36 | - legacy_random
37 | - modifier_order
38 | - multiline_arguments
39 | - multiline_function_chains
40 | - multiline_parameters
41 | - nimble_operator
42 | - operator_usage_whitespace
43 | - overridden_super_call
44 | - prefer_self_type_over_type_of_self
45 | - prohibited_super_call
46 | - quick_discouraged_focused_test
47 | - quick_discouraged_pending_test
48 | - reduce_into
49 | - redundant_nil_coalescing
50 | - redundant_type_annotation
51 | - single_test_class
52 | - sorted_first_last
53 | - sorted_imports
54 | - static_operator
55 | - strict_fileprivate
56 | - switch_case_on_newline
57 | - toggle_bool
58 | - unneeded_parentheses_in_closure_argument
59 | - unused_import
60 | - vertical_parameter_alignment_on_call
61 | - vertical_whitespace_closing_braces
62 | - yoda_condition
63 |
64 | # configurable rules
65 | cyclomatic_complexity:
66 | warning: 10
67 | error: 15
68 |
69 | file_length:
70 | warning: 600
71 | error: 1000
72 |
73 | function_body_length:
74 | warning: 50
75 | error: 100
76 |
77 | function_parameter_count:
78 | warning: 6
79 | error: 8
80 |
81 | line_length:
82 | warning: 120
83 | error: 150
84 |
85 | type_body_length:
86 | warning: 300
87 | error: 400
88 |
89 | reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji)
90 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | os: osx
3 | osx_image: xcode11.5
4 | jobs:
5 | include:
6 | - stage: "Build & Test"
7 | script: xcodebuild -workspace MultiProgressView.xcworkspace -scheme SwiftLint -sdk iphonesimulator -destination platform="iOS Simulator,name=iPhone 11 Pro Max,OS=13.5"
8 | name: "Run SwiftLint"
9 | - script: xcodebuild test -workspace MultiProgressView.xcworkspace -scheme MultiProgressView -sdk iphonesimulator -destination platform="iOS Simulator,name=iPhone 11 Pro Max,OS=13.5"
10 | name: "Run Unit Tests"
11 | - script: xcodebuild -workspace MultiProgressView.xcworkspace -scheme MultiProgressViewExample -sdk iphonesimulator -destination platform="iOS Simulator,name=iPhone 11 Pro Max,OS=13.5"
12 | name: "Build Example Project"
13 |
14 | # upload codecov report
15 | after_success: bash <(curl -s https://codecov.io/bash) -J 'MultiProgressView'
16 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 | - If you **found a bug**, open an issue and tag as bug.
3 | - If you **have a feature request**, open an issue and tag as feature.
4 | - If you **want to contribute**, submit a pull request.
5 | - In order to submit a pull request, please fork this repo and submit a pull request from your forked repo.
6 | - Have a detailed message as to what your pull request fixes/enhances/adds.
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | // swiftlint:disable discouraged_optional_collection
28 | @UIApplicationMain
29 | class AppDelegate: UIResponder, UIApplicationDelegate {
30 |
31 | var window: UIWindow?
32 |
33 | func application(_ application: UIApplication,
34 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
35 | window = UIWindow(frame: UIScreen.main.bounds)
36 | window?.makeKeyAndVisible()
37 | let navigationController = UINavigationController(rootViewController: DemoViewController())
38 | window?.rootViewController = navigationController
39 | return true
40 | }
41 | }
42 | // swiftlint:enable discouraged_optional_collection
43 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/DemoViewController.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | class DemoViewController: UITableViewController {
28 |
29 | override func viewDidLoad() {
30 | super.viewDidLoad()
31 | navigationItem.title = "Demo"
32 | tableView.tableFooterView = UIView()
33 | }
34 |
35 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
36 | let cell = UITableViewCell()
37 | cell.textLabel?.font = UIFont.systemFont(ofSize: 14)
38 |
39 | switch indexPath.row {
40 | case 0:
41 | cell.textLabel?.text = "Single Progress View (Programmatic)"
42 | case 1:
43 | cell.textLabel?.text = "Multiple Progress Views (Storyboard)"
44 | default:
45 | break
46 | }
47 | return cell
48 | }
49 |
50 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
51 | switch indexPath.row {
52 | case 0:
53 | navigationController?.pushViewController(StorageExampleViewController(), animated: true)
54 | case 1:
55 | let storyboard = UIStoryboard(name: "LanguageExample", bundle: nil)
56 | let viewController = storyboard.instantiateViewController(withIdentifier: "LanguageExampleViewController")
57 | navigationController?.pushViewController(viewController, animated: true)
58 | default:
59 | break
60 | }
61 | }
62 |
63 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
64 | return 2
65 | }
66 |
67 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
68 | return 50
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Example/Extensions/UIColor+Extensions.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | extension UIColor {
28 |
29 | static func rgb(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
30 | return UIColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: 1)
31 | }
32 |
33 | enum StorageExample {
34 | static let progressRed = UIColor.rgb(red: 251, green: 16, blue: 68)
35 | static let progressGreen = UIColor.rgb(red: 67, green: 213, blue: 82)
36 | static let progressPurple = UIColor.rgb(red: 70, green: 58, blue: 205)
37 | static let progressYellow = UIColor.rgb(red: 252, green: 196, blue: 9)
38 | static let progressBlue = UIColor.rgb(red: 10, green: 96, blue: 253)
39 | static let progressOrange = UIColor.rgb(red: 251, green: 128, blue: 7)
40 | static let progressGray = UIColor.rgb(red: 188, green: 186, blue: 194)
41 | static let progressBackground = UIColor.rgb(red: 224, green: 224, blue: 224)
42 |
43 | static let backgroundGray = UIColor.rgb(red: 235, green: 235, blue: 242)
44 | static let borderColor = UIColor.rgb(red: 189, green: 189, blue: 189)
45 | }
46 |
47 | enum LanguageExample {
48 | static let progressBlueDark = UIColor.rgb(red: 45, green: 94, blue: 146)
49 | static let progressBlueLight = UIColor.rgb(red: 54, green: 117, blue: 190)
50 | static let progressGreenDark = UIColor.rgb(red: 65, green: 136, blue: 61)
51 | static let progressGreenLight = UIColor.rgb(red: 77, green: 173, blue: 74)
52 | static let progressCyanDark = UIColor.rgb(red: 63, green: 141, blue: 167)
53 | static let progressCyanLight = UIColor.rgb(red: 79, green: 177, blue: 216)
54 | static let progressYellowDark = UIColor.rgb(red: 182, green: 125, blue: 51)
55 | static let progressYellowLight = UIColor.rgb(red: 233, green: 158, blue: 60)
56 | static let progressRedDark = UIColor.rgb(red: 160, green: 51, blue: 52)
57 | static let progressRedLight = UIColor.rgb(red: 204, green: 61, blue: 62)
58 |
59 | static let borderColor = UIColor.rgb(red: 189, green: 189, blue: 189)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Example/Extensions/UIView+Extensions.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | extension UIView {
28 |
29 | @discardableResult
30 | func anchor(top: NSLayoutYAxisAnchor? = nil,
31 | left: NSLayoutXAxisAnchor? = nil,
32 | bottom: NSLayoutYAxisAnchor? = nil,
33 | right: NSLayoutXAxisAnchor? = nil,
34 | paddingTop: CGFloat = 0,
35 | paddingLeft: CGFloat = 0,
36 | paddingBottom: CGFloat = 0,
37 | paddingRight: CGFloat = 0,
38 | width: CGFloat = 0,
39 | height: CGFloat = 0) -> [NSLayoutConstraint] {
40 | translatesAutoresizingMaskIntoConstraints = false
41 |
42 | var anchors = [NSLayoutConstraint]()
43 |
44 | if let top = top {
45 | anchors.append(topAnchor.constraint(equalTo: top, constant: paddingTop))
46 | }
47 | if let left = left {
48 | anchors.append(leftAnchor.constraint(equalTo: left, constant: paddingLeft))
49 | }
50 | if let bottom = bottom {
51 | anchors.append(bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom))
52 | }
53 | if let right = right {
54 | anchors.append(rightAnchor.constraint(equalTo: right, constant: -paddingRight))
55 | }
56 | if width > 0 {
57 | anchors.append(widthAnchor.constraint(equalToConstant: width))
58 | }
59 | if height > 0 {
60 | anchors.append(heightAnchor.constraint(equalToConstant: height))
61 | }
62 |
63 | anchors.forEach({ $0.isActive = true })
64 |
65 | return anchors
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Example/LanguageExample/CodingLanguage.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | enum CodingLanguage: Int {
28 | case none, html, net, java, javascript, css
29 |
30 | var description: String {
31 | switch self {
32 | case .none:
33 | return "Language"
34 | case .html:
35 | return "HTML/HTML5"
36 | case .net:
37 | return "ASP.Net"
38 | case .java:
39 | return "Java"
40 | case .javascript:
41 | return "JavaScript/jQuery"
42 | case .css:
43 | return "CSS/CSS3"
44 | }
45 | }
46 |
47 | var darkColor: UIColor {
48 | switch self {
49 | case .none:
50 | return .black
51 | case .html:
52 | return UIColor.LanguageExample.progressBlueDark
53 | case .net:
54 | return UIColor.LanguageExample.progressGreenDark
55 | case .java:
56 | return UIColor.LanguageExample.progressCyanDark
57 | case .javascript:
58 | return UIColor.LanguageExample.progressYellowDark
59 | case .css:
60 | return UIColor.LanguageExample.progressRedDark
61 | }
62 | }
63 |
64 | var lightColor: UIColor {
65 | switch self {
66 | case .none:
67 | return .black
68 | case .html:
69 | return UIColor.LanguageExample.progressBlueLight
70 | case .net:
71 | return UIColor.LanguageExample.progressGreenLight
72 | case .java:
73 | return UIColor.LanguageExample.progressCyanLight
74 | case .javascript:
75 | return UIColor.LanguageExample.progressYellowLight
76 | case .css:
77 | return UIColor.LanguageExample.progressRedLight
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Example/LanguageExample/LanguageExampleProgressView.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import MultiProgressView
26 | import UIKit
27 |
28 | @IBDesignable
29 | class LanguageExampleProgressView: MultiProgressView {
30 |
31 | @IBInspectable var language: Int = 0 {
32 | didSet {
33 | titleLabel.text = CodingLanguage(rawValue: language)?.description
34 | }
35 | }
36 |
37 | @IBInspectable var percentage: Int = 0 {
38 | didSet {
39 | percentageLabel.text = "\(percentage)%"
40 | }
41 | }
42 |
43 | private let titleLabel: UILabel = {
44 | let label = UILabel()
45 | label.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
46 | label.textColor = .white
47 | return label
48 | }()
49 |
50 | private let percentageLabel: UILabel = {
51 | let label = UILabel()
52 | label.font = UIFont.systemFont(ofSize: 12, weight: .semibold)
53 | return label
54 | }()
55 |
56 | override init(frame: CGRect) {
57 | super.init(frame: frame)
58 | initialize()
59 | }
60 |
61 | required init?(coder aDecoder: NSCoder) {
62 | super.init(coder: aDecoder)
63 | initialize()
64 | }
65 |
66 | private func initialize() {
67 | setupLabels()
68 | lineCap = .round
69 | titleLabel.isHidden = true
70 | }
71 |
72 | private func setupLabels() {
73 | addSubview(titleLabel)
74 | titleLabel.anchor(left: leftAnchor, paddingLeft: 8)
75 | titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
76 |
77 | addSubview(percentageLabel)
78 | percentageLabel.anchor(right: rightAnchor, paddingRight: 8)
79 | percentageLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
80 | }
81 |
82 | func shouldHideTitle(_ hide: Bool) {
83 | titleLabel.isHidden = hide
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Example/MultiProgressViewExample.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 |
33 | UISupportedInterfaceOrientations~ipad
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationPortraitUpsideDown
37 | UIInterfaceOrientationLandscapeLeft
38 | UIInterfaceOrientationLandscapeRight
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Example/StorageExample/StorageProgressSection.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import MultiProgressView
26 | import UIKit
27 |
28 | class StorageProgressSection: ProgressViewSection {
29 |
30 | private let rightBorder: UIView = {
31 | let border = UIView()
32 | border.backgroundColor = .white
33 | return border
34 | }()
35 |
36 | func configure(withStorageType storageType: StorageType) {
37 | addSubview(rightBorder)
38 | rightBorder.anchor(top: topAnchor, bottom: bottomAnchor, right: rightAnchor, width: 1)
39 | backgroundColor = storageType.color
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Example/StorageExample/StorageStackView.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | class StorageStackView: UIStackView {
28 |
29 | private let titleLabel: UILabel = {
30 | let label = UILabel()
31 | label.font = UIFont.systemFont(ofSize: 11)
32 | return label
33 | }()
34 |
35 | private lazy var colorView: UIView = {
36 | let view = UIView()
37 | view.layer.cornerRadius = colorViewHeight / 4
38 | view.layer.masksToBounds = true
39 | return view
40 | }()
41 |
42 | private let colorViewHeight: CGFloat = 11
43 |
44 | init(storageType: StorageType) {
45 | super.init(frame: .zero)
46 | alignment = .fill
47 | spacing = 6
48 |
49 | addArrangedSubview(colorView)
50 | colorView.anchor(width: colorViewHeight, height: colorViewHeight)
51 | colorView.backgroundColor = storageType.color
52 |
53 | addArrangedSubview(titleLabel)
54 | titleLabel.text = storageType.description
55 | }
56 |
57 | required init(coder: NSCoder) {
58 | fatalError("init(coder:) has not been implemented")
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Example/StorageExample/StorageType.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | enum StorageType: Int {
28 | case app, message, media, photo, mail, unknown, other
29 |
30 | static var allTypes: [StorageType] = [.app, .message, .media, .photo, .mail, .unknown, .other]
31 |
32 | var description: String {
33 | switch self {
34 | case .app:
35 | return "Apps"
36 | case .message:
37 | return "Messages"
38 | case .media:
39 | return "Media"
40 | case .photo:
41 | return "Photos"
42 | case .mail:
43 | return "Mail"
44 | case .unknown:
45 | return ""
46 | case .other:
47 | return "Other"
48 | }
49 | }
50 |
51 | var color: UIColor {
52 | switch self {
53 | case .app:
54 | return UIColor.StorageExample.progressRed
55 | case .message:
56 | return UIColor.StorageExample.progressGreen
57 | case .media:
58 | return UIColor.StorageExample.progressPurple
59 | case .photo:
60 | return UIColor.StorageExample.progressYellow
61 | case .mail:
62 | return UIColor.StorageExample.progressBlue
63 | case .unknown:
64 | return UIColor.StorageExample.progressOrange
65 | case .other:
66 | return UIColor.StorageExample.progressGray
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Images/example1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/example1.gif
--------------------------------------------------------------------------------
/Images/example2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/example2.gif
--------------------------------------------------------------------------------
/Images/header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/header.png
--------------------------------------------------------------------------------
/Images/social_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/social_preview.png
--------------------------------------------------------------------------------
/Images/storyboard_data_source.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/storyboard_data_source.gif
--------------------------------------------------------------------------------
/Images/storyboard_ib_outlet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/storyboard_ib_outlet.gif
--------------------------------------------------------------------------------
/Images/storyboard_identity_inspector.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mac-gallagher/MultiProgressView/a912d50fa614a0f0f33a19e35e0836d8f3abbc98/Images/storyboard_identity_inspector.gif
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Mac Gallagher
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MultiProgressView.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "MultiProgressView"
4 | s.version = "1.3.0"
5 | s.platform = :ios, "9.0"
6 | s.summary = "A replacement for UIProgressView that depicts multiple progresses over time"
7 |
8 | s.description = <<-DESC
9 | A replacement for UIProgressView that depicts multiple progresses over time.
10 | DESC
11 |
12 | s.homepage = "https://github.com/mac-gallagher/MultiProgressView"
13 | s.documentation_url = "https://github.com/mac-gallagher/MultiProgressView/tree/master/README.md"
14 | s.license = { :type => 'MIT', :file => 'LICENSE' }
15 | s.author = { "Mac Gallagher" => "jmgallagher36@gmail.com" }
16 | s.source = { :git => "https://github.com/mac-gallagher/MultiProgressView.git", :tag => "v1.3.0" }
17 |
18 | s.swift_version = "5.0"
19 | s.source_files = "Sources/**/*.{h,swift}"
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/MultiProgressView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MultiProgressView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MultiProgressView.xcodeproj/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 | /
7 | /// MIT License
8 | ///
9 | /// Copyright (c) ___YEAR___ ___FULLUSERNAME___
10 | ///
11 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
12 | /// of this software and associated documentation files (the "Software"), to deal
13 | /// in the Software without restriction, including without limitation the rights
14 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | /// copies of the Software, and to permit persons to whom the Software is
16 | /// furnished to do so, subject to the following conditions:
17 | ///
18 | /// The above copyright notice and this permission notice shall be included in all
19 | /// copies or substantial portions of the Software.
20 | ///
21 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | /// SOFTWARE.
28 | ///
29 |
30 |
31 |
--------------------------------------------------------------------------------
/MultiProgressView.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/MultiProgressView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MultiProgressView.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Nimble",
6 | "repositoryURL": "https://github.com/Quick/Nimble",
7 | "state": {
8 | "branch": null,
9 | "revision": "f8657642dfdec9973efc79cc68bcef43a653a2bc",
10 | "version": "8.0.2"
11 | }
12 | },
13 | {
14 | "package": "Quick",
15 | "repositoryURL": "https://github.com/Quick/Quick",
16 | "state": {
17 | "branch": null,
18 | "revision": "94df9b449508344667e5afc7e80f8bcbff1e4c37",
19 | "version": "2.1.0"
20 | }
21 | }
22 | ]
23 | },
24 | "version": 1
25 | }
26 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.0
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "MultiProgressView",
8 | platforms: [
9 | .iOS(.v9)
10 | ],
11 | products: [
12 | .library(
13 | name: "MultiProgressView",
14 | targets: ["MultiProgressView"]),
15 | ],
16 | dependencies: [
17 | .package(url: "https://github.com/Quick/Quick", from: "2.1.0"),
18 | .package(url: "https://github.com/Quick/Nimble", from: "8.0.2")
19 | ],
20 | targets: [
21 | .target(
22 | name: "MultiProgressView",
23 | dependencies: []),
24 | .testTarget(
25 | name: "MultiProgressViewTests",
26 | dependencies: [
27 | "MultiProgressView",
28 | "Quick",
29 | "Nimble"
30 | ]
31 | )
32 | ]
33 | )
34 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | platform :ios, '9.0'
4 |
5 | workspace 'MultiProgressView'
6 |
7 | target 'MultiProgressViewTests' do
8 | pod 'Quick', '>= 2.1.0'
9 | pod 'Nimble', '>= 8.0.2'
10 | end
11 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Nimble (8.0.2)
3 | - Quick (2.1.0)
4 |
5 | DEPENDENCIES:
6 | - Nimble (>= 8.0.2)
7 | - Quick (>= 2.1.0)
8 |
9 | SPEC REPOS:
10 | https://github.com/cocoapods/specs.git:
11 | - Nimble
12 | - Quick
13 |
14 | SPEC CHECKSUMS:
15 | Nimble: 622629381bda1dd5678162f21f1368cec7cbba60
16 | Quick: 4be43f6634acfa727dd106bdf3929ce125ffa79d
17 |
18 | PODFILE CHECKSUM: 12722990d4c51f0f49ab87b5c08ff7edfa368301
19 |
20 | COCOAPODS: 1.6.1
21 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Nimble (8.0.2)
3 | - Quick (2.1.0)
4 |
5 | DEPENDENCIES:
6 | - Nimble (>= 8.0.2)
7 | - Quick (>= 2.1.0)
8 |
9 | SPEC REPOS:
10 | https://github.com/cocoapods/specs.git:
11 | - Nimble
12 | - Quick
13 |
14 | SPEC CHECKSUMS:
15 | Nimble: 622629381bda1dd5678162f21f1368cec7cbba60
16 | Quick: 4be43f6634acfa727dd106bdf3929ce125ffa79d
17 |
18 | PODFILE CHECKSUM: 12722990d4c51f0f49ab87b5c08ff7edfa368301
19 |
20 | COCOAPODS: 1.6.1
21 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchException/CwlCatchException.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CwlCatchException.swift
3 | // CwlAssertionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | import Foundation
22 |
23 | #if SWIFT_PACKAGE
24 | import CwlCatchExceptionSupport
25 | #endif
26 |
27 | private func catchReturnTypeConverter(_ type: T.Type, block: () -> Void) -> T? {
28 | return catchExceptionOfKind(type, block) as? T
29 | }
30 |
31 | extension NSException {
32 | public static func catchException(in block: () -> Void) -> Self? {
33 | return catchReturnTypeConverter(self, block: block)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/CwlCatchException.m:
--------------------------------------------------------------------------------
1 | //
2 | // CwlCatchException.m
3 | // CwlAssertionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | #import "CwlCatchException.h"
22 |
23 | #if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
24 | __attribute__((visibility("hidden")))
25 | #endif
26 | NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void)) {
27 | @try {
28 | inBlock();
29 | } @catch (NSException *exception) {
30 | if ([exception isKindOfClass:type]) {
31 | return exception;
32 | } else {
33 | @throw;
34 | }
35 | }
36 | return nil;
37 | }
38 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlCatchException/Sources/CwlCatchExceptionSupport/include/CwlCatchException.h:
--------------------------------------------------------------------------------
1 | //
2 | // CwlCatchException.h
3 | // CwlCatchException
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | #import
22 |
23 | //! Project version number for CwlCatchException.
24 | FOUNDATION_EXPORT double CwlCatchExceptionVersionNumber;
25 |
26 | //! Project version string for CwlCatchException.
27 | FOUNDATION_EXPORT const unsigned char CwlCatchExceptionVersionString[];
28 |
29 | #if !SWIFT_PACKAGE && NON_SWIFT_PACKAGE
30 | __attribute__((visibility("hidden")))
31 | #endif
32 | NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)(void));
33 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m:
--------------------------------------------------------------------------------
1 | //
2 | // CwlMachBadExceptionHandler.m
3 | // CwlPreconditionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | #if defined(__x86_64__)
22 |
23 | #import "mach_excServer.h"
24 | #import "CwlMachBadInstructionHandler.h"
25 |
26 | @protocol BadInstructionReply
27 | +(NSNumber *)receiveReply:(NSValue *)value;
28 | @end
29 |
30 | /// A basic function that receives callbacks from mach_exc_server and relays them to the Swift implemented BadInstructionException.catch_mach_exception_raise_state.
31 | kern_return_t catch_mach_exception_raise_state(mach_port_t exception_port, exception_type_t exception, const mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, const thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
32 | bad_instruction_exception_reply_t reply = { exception_port, exception, code, codeCnt, flavor, old_state, old_stateCnt, new_state, new_stateCnt };
33 | Class badInstructionClass = NSClassFromString(@"BadInstructionException");
34 | NSValue *value = [NSValue valueWithBytes: &reply objCType: @encode(bad_instruction_exception_reply_t)];
35 | return [[badInstructionClass performSelector: @selector(receiveReply:) withObject: value] intValue];
36 | }
37 |
38 | // The mach port should be configured so that this function is never used.
39 | kern_return_t catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) {
40 | assert(false);
41 | return KERN_FAILURE;
42 | }
43 |
44 | // The mach port should be configured so that this function is never used.
45 | kern_return_t catch_mach_exception_raise_state_identity(mach_port_t exception_port, mach_port_t thread, mach_port_t task, exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, mach_msg_type_number_t old_stateCnt, thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) {
46 | assert(false);
47 | return KERN_FAILURE;
48 | }
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h:
--------------------------------------------------------------------------------
1 | //
2 | // CwlMachBadInstructionHandler.h
3 | // CwlPreconditionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | #import
22 | #import
23 |
24 | NS_ASSUME_NONNULL_BEGIN
25 |
26 | extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
27 |
28 | // The request_mach_exception_raise_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift.
29 | typedef struct
30 | {
31 | mach_msg_header_t Head;
32 | /* start of the kernel processed data */
33 | mach_msg_body_t msgh_body;
34 | mach_msg_port_descriptor_t thread;
35 | mach_msg_port_descriptor_t task;
36 | /* end of the kernel processed data */
37 | NDR_record_t NDR;
38 | exception_type_t exception;
39 | mach_msg_type_number_t codeCnt;
40 | int64_t code[2];
41 | int flavor;
42 | mach_msg_type_number_t old_stateCnt;
43 | natural_t old_state[224];
44 | } request_mach_exception_raise_t;
45 |
46 | // The reply_mach_exception_raise_state_t struct is passed to mach_msg which assumes its exact layout. To avoid problems with different layouts, we keep the definition in C rather than Swift.
47 | typedef struct
48 | {
49 | mach_msg_header_t Head;
50 | NDR_record_t NDR;
51 | kern_return_t RetCode;
52 | int flavor;
53 | mach_msg_type_number_t new_stateCnt;
54 | natural_t new_state[224];
55 | } reply_mach_exception_raise_state_t;
56 |
57 | typedef struct
58 | {
59 | mach_port_t exception_port;
60 | exception_type_t exception;
61 | mach_exception_data_type_t const * _Nullable code;
62 | mach_msg_type_number_t codeCnt;
63 | int32_t * _Nullable flavor;
64 | natural_t const * _Nullable old_state;
65 | mach_msg_type_number_t old_stateCnt;
66 | thread_state_t _Nullable new_state;
67 | mach_msg_type_number_t * _Nullable new_stateCnt;
68 | } bad_instruction_exception_reply_t;
69 |
70 | NS_ASSUME_NONNULL_END
71 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlBadInstructionException.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CwlBadInstructionException.swift
3 | // CwlPreconditionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | import Foundation
22 |
23 | #if SWIFT_PACKAGE
24 | import CwlMachBadInstructionHandler
25 | #endif
26 |
27 | private func raiseBadInstructionException() {
28 | BadInstructionException().raise()
29 | }
30 |
31 | /// A simple NSException subclass. It's not required to subclass NSException (since the exception type is represented in the name) but this helps for identifying the exception through runtime type.
32 | @objc(BadInstructionException)
33 | public class BadInstructionException: NSException {
34 | static var name: String = "com.cocoawithlove.BadInstruction"
35 |
36 | init() {
37 | super.init(name: NSExceptionName(rawValue: BadInstructionException.name), reason: nil, userInfo: nil)
38 | }
39 |
40 | required public init?(coder aDecoder: NSCoder) {
41 | super.init(coder: aDecoder)
42 | }
43 |
44 | /// An Objective-C callable function, invoked from the `mach_exc_server` callback function `catch_mach_exception_raise_state` to push the `raiseBadInstructionException` function onto the stack.
45 | @objc(receiveReply:)
46 | public class func receiveReply(_ value: NSValue) -> NSNumber {
47 | #if arch(x86_64)
48 | var reply = bad_instruction_exception_reply_t(exception_port: 0, exception: 0, code: nil, codeCnt: 0, flavor: nil, old_state: nil, old_stateCnt: 0, new_state: nil, new_stateCnt: nil)
49 | withUnsafeMutablePointer(to: &reply) { value.getValue(UnsafeMutableRawPointer($0)) }
50 |
51 | let old_state: UnsafePointer = reply.old_state!
52 | let old_stateCnt: mach_msg_type_number_t = reply.old_stateCnt
53 | let new_state: thread_state_t = reply.new_state!
54 | let new_stateCnt: UnsafeMutablePointer = reply.new_stateCnt!
55 |
56 | // Make sure we've been given enough memory
57 | if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT {
58 | return NSNumber(value: KERN_INVALID_ARGUMENT)
59 | }
60 |
61 | // Read the old thread state
62 | var state = old_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { return $0.pointee }
63 |
64 | // 1. Decrement the stack pointer
65 | state.__rsp -= __uint64_t(MemoryLayout.size)
66 |
67 | // 2. Save the old Instruction Pointer to the stack.
68 | if let pointer = UnsafeMutablePointer<__uint64_t>(bitPattern: UInt(state.__rsp)) {
69 | pointer.pointee = state.__rip
70 | } else {
71 | return NSNumber(value: KERN_INVALID_ARGUMENT)
72 | }
73 |
74 | // 3. Set the Instruction Pointer to the new function's address
75 | var f: @convention(c) () -> Void = raiseBadInstructionException
76 | withUnsafePointer(to: &f) {
77 | state.__rip = $0.withMemoryRebound(to: __uint64_t.self, capacity: 1) { return $0.pointee }
78 | }
79 |
80 | // Write the new thread state
81 | new_state.withMemoryRebound(to: x86_thread_state64_t.self, capacity: 1) { $0.pointee = state }
82 | new_stateCnt.pointee = x86_THREAD_STATE64_COUNT
83 |
84 | return NSNumber(value: KERN_SUCCESS)
85 | #else
86 | fatalError("Unavailable for this CPU architecture")
87 | #endif
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/CwlDarwinDefinitions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CwlDarwinDefinitions.swift
3 | // CwlPreconditionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | import Darwin
22 |
23 | #if arch(x86_64)
24 |
25 | // From /usr/include/mach/message.h
26 | // #define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
27 | // #define MACH_MSGH_BITS_REMOTE(bits) \
28 | // ((bits) & MACH_MSGH_BITS_REMOTE_MASK)
29 | // #define MACH_MSGH_BITS(remote, local) /* legacy */ \
30 | // ((remote) | ((local) << 8))
31 | public let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20
32 | public func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) }
33 | public func MACH_MSGH_BITS(_ remote: UInt32, _ local: UInt32) -> UInt32 { return ((remote) | ((local) << 8)) }
34 |
35 | // From /usr/include/mach/exception_types.h
36 | // #define EXC_BAD_INSTRUCTION 2 /* Instruction failed */
37 | // #define EXC_MASK_BAD_INSTRUCTION (1 << EXC_BAD_INSTRUCTION)
38 | public let EXC_BAD_INSTRUCTION: UInt32 = 2
39 | public let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION
40 |
41 | // From /usr/include/mach/i386/thread_status.h
42 | // #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
43 | // ( sizeof (x86_thread_state64_t) / sizeof (int) ))
44 | public let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size)
45 |
46 | public let EXC_TYPES_COUNT = 14
47 | public struct execTypesCountTuple {
48 | // From /usr/include/mach/i386/exception.h
49 | // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */
50 | public var value: (T, T, T, T, T, T, T, T, T, T, T, T, T, T) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
51 | public init() {
52 | }
53 | }
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/Pods/Nimble/Carthage/Checkouts/CwlPreconditionTesting/Sources/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h:
--------------------------------------------------------------------------------
1 | //
2 | // CwlPreconditionTesting.h
3 | // CwlPreconditionTesting
4 | //
5 | // Created by Matt Gallagher on 2016/01/10.
6 | // Copyright © 2016 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
7 | //
8 | // Permission to use, copy, modify, and/or distribute this software for any
9 | // purpose with or without fee is hereby granted, provided that the above
10 | // copyright notice and this permission notice appear in all copies.
11 | //
12 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
15 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 | //
20 |
21 | #import
22 |
23 | extern bool _swift_reportFatalErrorsToDebugger;
24 |
25 | //! Project version number for CwlUtils.
26 | FOUNDATION_EXPORT double CwlPreconditionTestingVersionNumber;
27 |
28 | //! Project version string for CwlUtils.
29 | FOUNDATION_EXPORT const unsigned char CwlAssertingTestingVersionString[];
30 |
31 | #include "CwlMachBadInstructionHandler.h"
32 | #include "CwlCatchException.h"
33 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// Protocol for the assertion handler that Nimble uses for all expectations.
4 | public protocol AssertionHandler {
5 | func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation)
6 | }
7 |
8 | /// Global backing interface for assertions that Nimble creates.
9 | /// Defaults to a private test handler that passes through to XCTest.
10 | ///
11 | /// If XCTest is not available, you must assign your own assertion handler
12 | /// before using any matchers, otherwise Nimble will abort the program.
13 | ///
14 | /// @see AssertionHandler
15 | public var NimbleAssertionHandler: AssertionHandler = { () -> AssertionHandler in
16 | // swiftlint:disable:previous identifier_name
17 | return isXCTestAvailable() ? NimbleXCTestHandler() : NimbleXCTestUnavailableHandler()
18 | }()
19 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift:
--------------------------------------------------------------------------------
1 | /// AssertionDispatcher allows multiple AssertionHandlers to receive
2 | /// assertion messages.
3 | ///
4 | /// @warning Does not fully dispatch if one of the handlers raises an exception.
5 | /// This is possible with XCTest-based assertion handlers.
6 | ///
7 | public class AssertionDispatcher: AssertionHandler {
8 | let handlers: [AssertionHandler]
9 |
10 | public init(handlers: [AssertionHandler]) {
11 | self.handlers = handlers
12 | }
13 |
14 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
15 | for handler in handlers {
16 | handler.assert(assertion, message: message, location: location)
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | #if canImport(Darwin)
4 |
5 | // swiftlint:disable line_length
6 | public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) throws -> Bool
7 | public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) throws -> Bool
8 | // swiftlint:enable line_length
9 |
10 | public class NMBObjCMatcher: NSObject, NMBMatcher {
11 | // swiftlint:disable identifier_name
12 | let _match: MatcherBlock
13 | let _doesNotMatch: MatcherBlock
14 | // swiftlint:enable identifier_name
15 | let canMatchNil: Bool
16 |
17 | public init(canMatchNil: Bool, matcher: @escaping MatcherBlock, notMatcher: @escaping MatcherBlock) {
18 | self.canMatchNil = canMatchNil
19 | self._match = matcher
20 | self._doesNotMatch = notMatcher
21 | }
22 |
23 | public convenience init(matcher: @escaping MatcherBlock) {
24 | self.init(canMatchNil: true, matcher: matcher)
25 | }
26 |
27 | public convenience init(canMatchNil: Bool, matcher: @escaping MatcherBlock) {
28 | self.init(canMatchNil: canMatchNil, matcher: matcher, notMatcher: ({ actualExpression, failureMessage in
29 | return try !matcher(actualExpression, failureMessage)
30 | }))
31 | }
32 |
33 | public convenience init(matcher: @escaping FullMatcherBlock) {
34 | self.init(canMatchNil: true, matcher: matcher)
35 | }
36 |
37 | public convenience init(canMatchNil: Bool, matcher: @escaping FullMatcherBlock) {
38 | self.init(canMatchNil: canMatchNil, matcher: ({ actualExpression, failureMessage in
39 | return try matcher(actualExpression, failureMessage, false)
40 | }), notMatcher: ({ actualExpression, failureMessage in
41 | return try matcher(actualExpression, failureMessage, true)
42 | }))
43 | }
44 |
45 | private func canMatch(_ actualExpression: Expression, failureMessage: FailureMessage) -> Bool {
46 | do {
47 | if !canMatchNil {
48 | if try actualExpression.evaluate() == nil {
49 | failureMessage.postfixActual = " (use beNil() to match nils)"
50 | return false
51 | }
52 | }
53 | } catch let error {
54 | failureMessage.actualValue = "an unexpected error thrown: \(error)"
55 | return false
56 | }
57 | return true
58 | }
59 |
60 | public func matches(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
61 | let expr = Expression(expression: actualBlock, location: location)
62 | let result: Bool
63 | do {
64 | result = try _match(expr, failureMessage)
65 | } catch let error {
66 | failureMessage.stringValue = "unexpected error thrown: <\(error)>"
67 | return false
68 | }
69 |
70 | if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
71 | return result
72 | } else {
73 | return false
74 | }
75 | }
76 |
77 | public func doesNotMatch(_ actualBlock: @escaping () -> NSObject?, failureMessage: FailureMessage, location: SourceLocation) -> Bool {
78 | let expr = Expression(expression: actualBlock, location: location)
79 | let result: Bool
80 | do {
81 | result = try _doesNotMatch(expr, failureMessage)
82 | } catch let error {
83 | failureMessage.stringValue = "unexpected error thrown: <\(error)>"
84 | return false
85 | }
86 |
87 | if self.canMatch(Expression(expression: actualBlock, location: location), failureMessage: failureMessage) {
88 | return result
89 | } else {
90 | return false
91 | }
92 | }
93 | }
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift:
--------------------------------------------------------------------------------
1 | import Dispatch
2 | import Foundation
3 |
4 | /// "Global" state of Nimble is stored here. Only DSL functions should access / be aware of this
5 | /// class' existence
6 | internal class NimbleEnvironment: NSObject {
7 | static var activeInstance: NimbleEnvironment {
8 | get {
9 | let env = Thread.current.threadDictionary["NimbleEnvironment"]
10 | if let env = env as? NimbleEnvironment {
11 | return env
12 | } else {
13 | let newEnv = NimbleEnvironment()
14 | self.activeInstance = newEnv
15 | return newEnv
16 | }
17 | }
18 | set {
19 | Thread.current.threadDictionary["NimbleEnvironment"] = newValue
20 | }
21 | }
22 |
23 | // swiftlint:disable:next todo
24 | // TODO: eventually migrate the global to this environment value
25 | var assertionHandler: AssertionHandler {
26 | get { return NimbleAssertionHandler }
27 | set { NimbleAssertionHandler = newValue }
28 | }
29 |
30 | var suppressTVOSAssertionWarning: Bool = false
31 | var awaiter: Awaiter
32 |
33 | override init() {
34 | let timeoutQueue = DispatchQueue.global(qos: .userInitiated)
35 | awaiter = Awaiter(
36 | waitLock: AssertionWaitLock(),
37 | asyncQueue: .main,
38 | timeoutQueue: timeoutQueue
39 | )
40 |
41 | super.init()
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import XCTest
3 |
4 | /// Default handler for Nimble. This assertion handler passes failures along to
5 | /// XCTest.
6 | public class NimbleXCTestHandler: AssertionHandler {
7 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
8 | if !assertion {
9 | recordFailure("\(message.stringValue)\n", location: location)
10 | }
11 | }
12 | }
13 |
14 | /// Alternative handler for Nimble. This assertion handler passes failures along
15 | /// to XCTest by attempting to reduce the failure message size.
16 | public class NimbleShortXCTestHandler: AssertionHandler {
17 | public func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
18 | if !assertion {
19 | let msg: String
20 | if let actual = message.actualValue {
21 | msg = "got: \(actual) \(message.postfixActual)"
22 | } else {
23 | msg = "expected \(message.to) \(message.postfixMessage)"
24 | }
25 | recordFailure("\(msg)\n", location: location)
26 | }
27 | }
28 | }
29 |
30 | /// Fallback handler in case XCTest is unavailable. This assertion handler will abort
31 | /// the program if it is invoked.
32 | class NimbleXCTestUnavailableHandler: AssertionHandler {
33 | func assert(_ assertion: Bool, message: FailureMessage, location: SourceLocation) {
34 | fatalError("XCTest is not available and no custom assertion handler was configured. Aborting.")
35 | }
36 | }
37 |
38 | #if !SWIFT_PACKAGE
39 | /// Helper class providing access to the currently executing XCTestCase instance, if any
40 | @objc final internal class CurrentTestCaseTracker: NSObject, XCTestObservation {
41 | @objc static let sharedInstance = CurrentTestCaseTracker()
42 |
43 | private(set) var currentTestCase: XCTestCase?
44 |
45 | private var stashed_swift_reportFatalErrorsToDebugger: Bool = false
46 |
47 | @objc func testCaseWillStart(_ testCase: XCTestCase) {
48 | #if swift(>=3.2)
49 | stashed_swift_reportFatalErrorsToDebugger = _swift_reportFatalErrorsToDebugger
50 | _swift_reportFatalErrorsToDebugger = false
51 | #endif
52 |
53 | currentTestCase = testCase
54 | }
55 |
56 | @objc func testCaseDidFinish(_ testCase: XCTestCase) {
57 | currentTestCase = nil
58 |
59 | #if swift(>=3.2)
60 | _swift_reportFatalErrorsToDebugger = stashed_swift_reportFatalErrorsToDebugger
61 | #endif
62 | }
63 | }
64 | #endif
65 |
66 | func isXCTestAvailable() -> Bool {
67 | #if canImport(Darwin)
68 | // XCTest is weakly linked and so may not be present
69 | return NSClassFromString("XCTestCase") != nil
70 | #else
71 | return true
72 | #endif
73 | }
74 |
75 | public func recordFailure(_ message: String, location: SourceLocation) {
76 | #if SWIFT_PACKAGE
77 | XCTFail("\(message)", file: location.file, line: location.line)
78 | #else
79 | if let testCase = CurrentTestCaseTracker.sharedInstance.currentTestCase {
80 | let line = Int(location.line)
81 | testCase.recordFailure(withDescription: message, inFile: location.file, atLine: line, expected: true)
82 | } else {
83 | let msg = """
84 | Attempted to report a test failure to XCTest while no test case was running. The failure was:
85 | \"\(message)\"
86 | It occurred at: \(location.file):\(location.line)
87 | """
88 | NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise()
89 | }
90 | #endif
91 | }
92 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/DSL.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// Make an expectation on a given actual value. The value given is lazily evaluated.
4 | public func expect(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation {
5 | return Expectation(
6 | expression: Expression(
7 | expression: expression,
8 | location: SourceLocation(file: file, line: line),
9 | isClosure: true))
10 | }
11 |
12 | /// Make an expectation on a given actual value. The closure is lazily invoked.
13 | public func expect(_ file: FileString = #file, line: UInt = #line, expression: @escaping () throws -> T?) -> Expectation {
14 | return Expectation(
15 | expression: Expression(
16 | expression: expression,
17 | location: SourceLocation(file: file, line: line),
18 | isClosure: true))
19 | }
20 |
21 | /// Always fails the test with a message and a specified location.
22 | public func fail(_ message: String, location: SourceLocation) {
23 | let handler = NimbleEnvironment.activeInstance.assertionHandler
24 | handler.assert(false, message: FailureMessage(stringValue: message), location: location)
25 | }
26 |
27 | /// Always fails the test with a message.
28 | public func fail(_ message: String, file: FileString = #file, line: UInt = #line) {
29 | fail(message, location: SourceLocation(file: file, line: line))
30 | }
31 |
32 | /// Always fails the test.
33 | public func fail(_ file: FileString = #file, line: UInt = #line) {
34 | fail("fail() always fails", file: file, line: line)
35 | }
36 |
37 | /// Like Swift's precondition(), but raises NSExceptions instead of sigaborts
38 | internal func nimblePrecondition(
39 | _ expr: @autoclosure() -> Bool,
40 | _ name: @autoclosure() -> String,
41 | _ message: @autoclosure() -> String,
42 | file: StaticString = #file,
43 | line: UInt = #line) {
44 | let result = expr()
45 | if !result {
46 | #if canImport(Darwin)
47 | let exception = NSException(
48 | name: NSExceptionName(name()),
49 | reason: message(),
50 | userInfo: nil
51 | )
52 | exception.raise()
53 | #else
54 | preconditionFailure("\(name()) - \(message())", file: file, line: line)
55 | #endif
56 | }
57 | }
58 |
59 | internal func internalError(_ msg: String, file: FileString = #file, line: UInt = #line) -> Never {
60 | // swiftlint:disable line_length
61 | fatalError(
62 | """
63 | Nimble Bug Found: \(msg) at \(file):\(line).
64 | Please file a bug to Nimble: https://github.com/Quick/Nimble/issues with the code snippet that caused this error.
65 | """
66 | )
67 | // swiftlint:enable line_length
68 | }
69 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/FailureMessage.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// Encapsulates the failure message that matchers can report to the end user.
4 | ///
5 | /// This is shared state between Nimble and matchers that mutate this value.
6 | public class FailureMessage: NSObject {
7 | public var expected: String = "expected"
8 | public var actualValue: String? = "" // empty string -> use default; nil -> exclude
9 | public var to: String = "to"
10 | public var postfixMessage: String = "match"
11 | public var postfixActual: String = ""
12 | /// An optional message that will be appended as a new line and provides additional details
13 | /// about the failure. This message will only be visible in the issue navigator / in logs but
14 | /// not directly in the source editor since only a single line is presented there.
15 | public var extendedMessage: String?
16 | public var userDescription: String?
17 |
18 | public var stringValue: String {
19 | get {
20 | if let value = _stringValueOverride {
21 | return value
22 | } else {
23 | return computeStringValue()
24 | }
25 | }
26 | set {
27 | _stringValueOverride = newValue
28 | }
29 | }
30 |
31 | // swiftlint:disable:next identifier_name
32 | internal var _stringValueOverride: String?
33 | internal var hasOverriddenStringValue: Bool {
34 | return _stringValueOverride != nil
35 | }
36 |
37 | public override init() {
38 | }
39 |
40 | public init(stringValue: String) {
41 | _stringValueOverride = stringValue
42 | }
43 |
44 | internal func stripNewlines(_ str: String) -> String {
45 | let whitespaces = CharacterSet.whitespacesAndNewlines
46 | return str
47 | .components(separatedBy: "\n")
48 | .map { line in line.trimmingCharacters(in: whitespaces) }
49 | .joined(separator: "")
50 | }
51 |
52 | internal func computeStringValue() -> String {
53 | var value = "\(expected) \(to) \(postfixMessage)"
54 | if let actualValue = actualValue {
55 | value = "\(expected) \(to) \(postfixMessage), got \(actualValue)\(postfixActual)"
56 | }
57 | value = stripNewlines(value)
58 |
59 | if let extendedMessage = extendedMessage {
60 | value += "\n\(stripNewlines(extendedMessage))"
61 | }
62 |
63 | if let userDescription = userDescription {
64 | return "\(userDescription)\n\(value)"
65 | }
66 |
67 | return value
68 | }
69 |
70 | internal func appendMessage(_ msg: String) {
71 | if hasOverriddenStringValue {
72 | stringValue += "\(msg)"
73 | } else if actualValue != nil {
74 | postfixActual += msg
75 | } else {
76 | postfixMessage += msg
77 | }
78 | }
79 |
80 | internal func appendDetails(_ msg: String) {
81 | if hasOverriddenStringValue {
82 | if let desc = userDescription {
83 | stringValue = "\(desc)\n\(stringValue)"
84 | }
85 | stringValue += "\n\(msg)"
86 | } else {
87 | if let desc = userDescription {
88 | userDescription = desc
89 | }
90 | extendedMessage = msg
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | private func matcherMessage(forType expectedType: T.Type) -> String {
4 | return "be a kind of \(String(describing: expectedType))"
5 | }
6 | private func matcherMessage(forClass expectedClass: AnyClass) -> String {
7 | return "be a kind of \(String(describing: expectedClass))"
8 | }
9 |
10 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class.
11 | public func beAKindOf(_ expectedType: T.Type) -> Predicate {
12 | return Predicate.define { actualExpression in
13 | let message: ExpectationMessage
14 |
15 | let instance = try actualExpression.evaluate()
16 | guard let validInstance = instance else {
17 | message = .expectedCustomValueTo(matcherMessage(forType: expectedType), "")
18 | return PredicateResult(status: .fail, message: message)
19 | }
20 | message = .expectedCustomValueTo(
21 | "be a kind of \(String(describing: expectedType))",
22 | "<\(String(describing: type(of: validInstance))) instance>"
23 | )
24 |
25 | return PredicateResult(
26 | bool: validInstance is T,
27 | message: message
28 | )
29 | }
30 | }
31 |
32 | #if canImport(Darwin)
33 |
34 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class.
35 | /// @see beAnInstanceOf if you want to match against the exact class
36 | public func beAKindOf(_ expectedClass: AnyClass) -> Predicate {
37 | return Predicate.define { actualExpression in
38 | let message: ExpectationMessage
39 | let status: PredicateStatus
40 |
41 | let instance = try actualExpression.evaluate()
42 | if let validInstance = instance {
43 | status = PredicateStatus(bool: instance != nil && instance!.isKind(of: expectedClass))
44 | message = .expectedCustomValueTo(
45 | matcherMessage(forClass: expectedClass),
46 | "<\(String(describing: type(of: validInstance))) instance>"
47 | )
48 | } else {
49 | status = .fail
50 | message = .expectedCustomValueTo(
51 | matcherMessage(forClass: expectedClass),
52 | ""
53 | )
54 | }
55 |
56 | return PredicateResult(status: status, message: message)
57 | }
58 | }
59 |
60 | extension NMBObjCMatcher {
61 | @objc public class func beAKindOfMatcher(_ expected: AnyClass) -> NMBMatcher {
62 | return NMBPredicate { actualExpression in
63 | return try beAKindOf(expected).satisfies(actualExpression).toObjectiveC()
64 | }
65 | }
66 | }
67 |
68 | #endif
69 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is an _exact_ instance of the given class.
4 | public func beAnInstanceOf(_ expectedType: T.Type) -> Predicate {
5 | let errorMessage = "be an instance of \(String(describing: expectedType))"
6 | return Predicate.define { actualExpression in
7 | let instance = try actualExpression.evaluate()
8 | guard let validInstance = instance else {
9 | return PredicateResult(
10 | status: .doesNotMatch,
11 | message: .expectedActualValueTo(errorMessage)
12 | )
13 | }
14 |
15 | let actualString = "<\(String(describing: type(of: validInstance))) instance>"
16 |
17 | return PredicateResult(
18 | status: PredicateStatus(bool: type(of: validInstance) == expectedType),
19 | message: .expectedCustomValueTo(errorMessage, actualString)
20 | )
21 | }
22 | }
23 |
24 | /// A Nimble matcher that succeeds when the actual value is an instance of the given class.
25 | /// @see beAKindOf if you want to match against subclasses
26 | public func beAnInstanceOf(_ expectedClass: AnyClass) -> Predicate {
27 | let errorMessage = "be an instance of \(String(describing: expectedClass))"
28 | return Predicate.define { actualExpression in
29 | let instance = try actualExpression.evaluate()
30 | let actualString: String
31 | if let validInstance = instance {
32 | actualString = "<\(String(describing: type(of: validInstance))) instance>"
33 | } else {
34 | actualString = ""
35 | }
36 | #if canImport(Darwin)
37 | let matches = instance != nil && instance!.isMember(of: expectedClass)
38 | #else
39 | let matches = instance != nil && type(of: instance!) == expectedClass
40 | #endif
41 | return PredicateResult(
42 | status: PredicateStatus(bool: matches),
43 | message: .expectedCustomValueTo(errorMessage, actualString)
44 | )
45 | }
46 | }
47 |
48 | #if canImport(Darwin)
49 | extension NMBObjCMatcher {
50 | @objc public class func beAnInstanceOfMatcher(_ expected: AnyClass) -> NMBMatcher {
51 | return NMBPredicate { actualExpression in
52 | return try beAnInstanceOf(expected).satisfies(actualExpression).toObjectiveC()
53 | }
54 | }
55 | }
56 | #endif
57 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value.
4 | public func beGreaterThan(_ expectedValue: T?) -> Predicate {
5 | let errorMessage = "be greater than <\(stringify(expectedValue))>"
6 | return Predicate.simple(errorMessage) { actualExpression in
7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue {
8 | return PredicateStatus(bool: actual > expected)
9 | }
10 | return .fail
11 | }
12 | }
13 |
14 | public func >(lhs: Expectation, rhs: T) {
15 | lhs.to(beGreaterThan(rhs))
16 | }
17 |
18 | #if canImport(Darwin) || !compiler(>=5.1)
19 | /// A Nimble matcher that succeeds when the actual value is greater than the expected value.
20 | public func beGreaterThan(_ expectedValue: NMBComparable?) -> Predicate {
21 | let errorMessage = "be greater than <\(stringify(expectedValue))>"
22 | return Predicate.simple(errorMessage) { actualExpression in
23 | let actualValue = try actualExpression.evaluate()
24 | let matches = actualValue != nil
25 | && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedDescending
26 | return PredicateStatus(bool: matches)
27 | }
28 | }
29 |
30 | public func > (lhs: Expectation, rhs: NMBComparable?) {
31 | lhs.to(beGreaterThan(rhs))
32 | }
33 | #endif
34 |
35 | #if canImport(Darwin)
36 | extension NMBObjCMatcher {
37 | @objc public class func beGreaterThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
38 | return NMBPredicate { actualExpression in
39 | let expr = actualExpression.cast { $0 as? NMBComparable }
40 | return try beGreaterThan(expected).satisfies(expr).toObjectiveC()
41 | }
42 | }
43 | }
44 | #endif
45 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is greater than
4 | /// or equal to the expected value.
5 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate {
6 | let message = "be greater than or equal to <\(stringify(expectedValue))>"
7 | return Predicate.simple(message) { actualExpression in
8 | let actualValue = try actualExpression.evaluate()
9 | if let actual = actualValue, let expected = expectedValue {
10 | return PredicateStatus(bool: actual >= expected)
11 | }
12 | return .fail
13 | }
14 | }
15 |
16 | public func >=(lhs: Expectation, rhs: T) {
17 | lhs.to(beGreaterThanOrEqualTo(rhs))
18 | }
19 |
20 | #if canImport(Darwin) || !compiler(>=5.1)
21 | /// A Nimble matcher that succeeds when the actual value is greater than
22 | /// or equal to the expected value.
23 | public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> Predicate {
24 | let message = "be greater than or equal to <\(stringify(expectedValue))>"
25 | return Predicate.simple(message) { actualExpression in
26 | let actualValue = try actualExpression.evaluate()
27 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) != ComparisonResult.orderedAscending
28 | return PredicateStatus(bool: matches)
29 | }
30 | }
31 |
32 | public func >=(lhs: Expectation, rhs: T) {
33 | lhs.to(beGreaterThanOrEqualTo(rhs))
34 | }
35 | #endif
36 |
37 | #if canImport(Darwin)
38 | extension NMBObjCMatcher {
39 | @objc public class func beGreaterThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
40 | return NMBPredicate { actualExpression in
41 | let expr = actualExpression.cast { $0 as? NMBComparable }
42 | return try beGreaterThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
43 | }
44 | }
45 | }
46 | #endif
47 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is the same instance
4 | /// as the expected instance.
5 | public func beIdenticalTo(_ expected: Any?) -> Predicate {
6 | return Predicate.define { actualExpression in
7 | let actual = try actualExpression.evaluate() as AnyObject?
8 |
9 | let bool = actual === (expected as AnyObject?) && actual !== nil
10 | return PredicateResult(
11 | bool: bool,
12 | message: .expectedCustomValueTo(
13 | "be identical to \(identityAsString(expected))",
14 | "\(identityAsString(actual))"
15 | )
16 | )
17 | }
18 | }
19 |
20 | public func === (lhs: Expectation, rhs: Any?) {
21 | lhs.to(beIdenticalTo(rhs))
22 | }
23 | public func !== (lhs: Expectation, rhs: Any?) {
24 | lhs.toNot(beIdenticalTo(rhs))
25 | }
26 |
27 | /// A Nimble matcher that succeeds when the actual value is the same instance
28 | /// as the expected instance.
29 | ///
30 | /// Alias for "beIdenticalTo".
31 | public func be(_ expected: Any?) -> Predicate {
32 | return beIdenticalTo(expected)
33 | }
34 |
35 | #if canImport(Darwin)
36 | extension NMBObjCMatcher {
37 | @objc public class func beIdenticalToMatcher(_ expected: NSObject?) -> NMBMatcher {
38 | return NMBPredicate { actualExpression in
39 | let aExpr = actualExpression.cast { $0 as Any? }
40 | return try beIdenticalTo(expected).satisfies(aExpr).toObjectiveC()
41 | }
42 | }
43 | }
44 | #endif
45 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeLessThan.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is less than the expected value.
4 | public func beLessThan(_ expectedValue: T?) -> Predicate {
5 | let message = "be less than <\(stringify(expectedValue))>"
6 | return Predicate.simple(message) { actualExpression in
7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue {
8 | return PredicateStatus(bool: actual < expected)
9 | }
10 | return .fail
11 | }
12 | }
13 |
14 | public func <(lhs: Expectation, rhs: T) {
15 | lhs.to(beLessThan(rhs))
16 | }
17 |
18 | #if canImport(Darwin) || !compiler(>=5.1)
19 | /// A Nimble matcher that succeeds when the actual value is less than the expected value.
20 | public func beLessThan(_ expectedValue: NMBComparable?) -> Predicate {
21 | let message = "be less than <\(stringify(expectedValue))>"
22 | return Predicate.simple(message) { actualExpression in
23 | let actualValue = try actualExpression.evaluate()
24 | let matches = actualValue != nil && actualValue!.NMB_compare(expectedValue) == ComparisonResult.orderedAscending
25 | return PredicateStatus(bool: matches)
26 | }
27 | }
28 |
29 | public func < (lhs: Expectation, rhs: NMBComparable?) {
30 | lhs.to(beLessThan(rhs))
31 | }
32 | #endif
33 |
34 | #if canImport(Darwin)
35 | extension NMBObjCMatcher {
36 | @objc public class func beLessThanMatcher(_ expected: NMBComparable?) -> NMBMatcher {
37 | return NMBPredicate { actualExpression in
38 | let expr = actualExpression.cast { $0 as? NMBComparable }
39 | return try beLessThan(expected).satisfies(expr).toObjectiveC()
40 | }
41 | }
42 | }
43 | #endif
44 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is less than
4 | /// or equal to the expected value.
5 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate {
6 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in
7 | if let actual = try actualExpression.evaluate(), let expected = expectedValue {
8 | return PredicateStatus(bool: actual <= expected)
9 | }
10 | return .fail
11 | }
12 | }
13 |
14 | public func <=(lhs: Expectation, rhs: T) {
15 | lhs.to(beLessThanOrEqualTo(rhs))
16 | }
17 |
18 | #if canImport(Darwin) || !compiler(>=5.1)
19 | /// A Nimble matcher that succeeds when the actual value is less than
20 | /// or equal to the expected value.
21 | public func beLessThanOrEqualTo(_ expectedValue: T?) -> Predicate {
22 | return Predicate.simple("be less than or equal to <\(stringify(expectedValue))>") { actualExpression in
23 | let actualValue = try actualExpression.evaluate()
24 | let matches = actualValue.map { $0.NMB_compare(expectedValue) != .orderedDescending } ?? false
25 | return PredicateStatus(bool: matches)
26 | }
27 | }
28 |
29 | public func <=(lhs: Expectation, rhs: T) {
30 | lhs.to(beLessThanOrEqualTo(rhs))
31 | }
32 | #endif
33 |
34 | #if canImport(Darwin)
35 | extension NMBObjCMatcher {
36 | @objc public class func beLessThanOrEqualToMatcher(_ expected: NMBComparable?) -> NMBMatcher {
37 | return NMBPredicate { actualExpression in
38 | let expr = actualExpression.cast { $0 as? NMBComparable }
39 | return try beLessThanOrEqualTo(expected).satisfies(expr).toObjectiveC()
40 | }
41 | }
42 | }
43 | #endif
44 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeNil.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is nil.
4 | public func beNil() -> Predicate {
5 | return Predicate.simpleNilable("be nil") { actualExpression in
6 | let actualValue = try actualExpression.evaluate()
7 | return PredicateStatus(bool: actualValue == nil)
8 | }
9 | }
10 |
11 | #if canImport(Darwin)
12 | extension NMBObjCMatcher {
13 | @objc public class func beNilMatcher() -> NMBMatcher {
14 | return NMBPredicate { actualExpression in
15 | return try beNil().satisfies(actualExpression).toObjectiveC()
16 | }
17 | }
18 | }
19 | #endif
20 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeVoid.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value is Void.
4 | public func beVoid() -> Predicate<()> {
5 | return Predicate.simpleNilable("be void") { actualExpression in
6 | let actualValue: ()? = try actualExpression.evaluate()
7 | return PredicateStatus(bool: actualValue != nil)
8 | }
9 | }
10 |
11 | extension Expectation where T == () {
12 | public static func == (lhs: Expectation<()>, rhs: ()) {
13 | lhs.to(beVoid())
14 | }
15 |
16 | public static func != (lhs: Expectation<()>, rhs: ()) {
17 | lhs.toNot(beVoid())
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/BeginWith.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual sequence's first element
4 | /// is equal to the expected value.
5 | public func beginWith(_ startingElement: T) -> Predicate
6 | where S.Iterator.Element == T {
7 | return Predicate.simple("begin with <\(startingElement)>") { actualExpression in
8 | if let actualValue = try actualExpression.evaluate() {
9 | var actualGenerator = actualValue.makeIterator()
10 | return PredicateStatus(bool: actualGenerator.next() == startingElement)
11 | }
12 | return .fail
13 | }
14 | }
15 |
16 | /// A Nimble matcher that succeeds when the actual collection's first element
17 | /// is equal to the expected object.
18 | public func beginWith(_ startingElement: Any) -> Predicate {
19 | return Predicate.simple("begin with <\(startingElement)>") { actualExpression in
20 | guard let collection = try actualExpression.evaluate() else { return .fail }
21 | guard collection.count > 0 else { return .doesNotMatch }
22 | #if os(Linux)
23 | guard let collectionValue = collection.object(at: 0) as? NSObject else {
24 | return .fail
25 | }
26 | #else
27 | let collectionValue = collection.object(at: 0) as AnyObject
28 | #endif
29 | return PredicateStatus(bool: collectionValue.isEqual(startingElement))
30 | }
31 | }
32 |
33 | /// A Nimble matcher that succeeds when the actual string contains expected substring
34 | /// where the expected substring's location is zero.
35 | public func beginWith(_ startingSubstring: String) -> Predicate {
36 | return Predicate.simple("begin with <\(startingSubstring)>") { actualExpression in
37 | if let actual = try actualExpression.evaluate() {
38 | return PredicateStatus(bool: actual.hasPrefix(startingSubstring))
39 | }
40 | return .fail
41 | }
42 | }
43 |
44 | #if canImport(Darwin)
45 | extension NMBObjCMatcher {
46 | @objc public class func beginWithMatcher(_ expected: Any) -> NMBMatcher {
47 | return NMBPredicate { actualExpression in
48 | let actual = try actualExpression.evaluate()
49 | if actual is String {
50 | let expr = actualExpression.cast { $0 as? String }
51 | // swiftlint:disable:next force_cast
52 | return try beginWith(expected as! String).satisfies(expr).toObjectiveC()
53 | } else {
54 | let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
55 | return try beginWith(expected).satisfies(expr).toObjectiveC()
56 | }
57 | }
58 | }
59 | }
60 | #endif
61 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> Predicate where S.Iterator.Element == T {
4 |
5 | return Predicate.define { actualExpression in
6 | let message: ExpectationMessage
7 | if predicateDescription == "" {
8 | message = .expectedTo("find object in collection that satisfies predicate")
9 | } else {
10 | message = .expectedTo("find object in collection \(predicateDescription)")
11 | }
12 |
13 | if let sequence = try actualExpression.evaluate() {
14 | for object in sequence {
15 | if predicate(object) {
16 | return PredicateResult(bool: true, message: message)
17 | }
18 | }
19 |
20 | return PredicateResult(bool: false, message: message)
21 | }
22 |
23 | return PredicateResult(status: .fail, message: message)
24 | }
25 | }
26 |
27 | #if canImport(Darwin)
28 | extension NMBObjCMatcher {
29 | @objc public class func containElementSatisfyingMatcher(_ predicate: @escaping ((NSObject) -> Bool)) -> NMBMatcher {
30 | return NMBPredicate { actualExpression in
31 | let value = try actualExpression.evaluate()
32 | guard let enumeration = value as? NSFastEnumeration else {
33 | let message = ExpectationMessage.fail(
34 | "containElementSatisfying must be provided an NSFastEnumeration object"
35 | )
36 | return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
37 | }
38 |
39 | let message = ExpectationMessage
40 | .expectedTo("find object in collection that satisfies predicate")
41 | .toObjectiveC()
42 |
43 | var iterator = NSFastEnumerationIterator(enumeration)
44 | while let item = iterator.next() {
45 | guard let object = item as? NSObject else {
46 | continue
47 | }
48 |
49 | if predicate(object) {
50 | return NMBPredicateResult(status: .matches, message: message)
51 | }
52 | }
53 |
54 | return NMBPredicateResult(status: .doesNotMatch, message: message)
55 | }
56 | }
57 | }
58 | #endif
59 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/ElementsEqual.swift:
--------------------------------------------------------------------------------
1 | /// A Nimble matcher that succeeds when the actual sequence contain the same elements in the same order to the exepected sequence.
2 | public func elementsEqual(_ expectedValue: S?) -> Predicate where S.Element: Equatable {
3 | // A matcher abstraction for https://developer.apple.com/documentation/swift/sequence/2949668-elementsequal
4 | return Predicate.define("elementsEqual <\(stringify(expectedValue))>") { (actualExpression, msg) in
5 | let actualValue = try actualExpression.evaluate()
6 | switch (expectedValue, actualValue) {
7 | case (nil, _?):
8 | return PredicateResult(status: .fail, message: msg.appendedBeNilHint())
9 | case (nil, nil), (_, nil):
10 | return PredicateResult(status: .fail, message: msg)
11 | case (let expected?, let actual?):
12 | let matches = expected.elementsEqual(actual)
13 | return PredicateResult(bool: matches, message: msg)
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/EndWith.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual sequence's last element
4 | /// is equal to the expected value.
5 | public func endWith(_ endingElement: T) -> Predicate
6 | where S.Iterator.Element == T {
7 | return Predicate.simple("end with <\(endingElement)>") { actualExpression in
8 | if let actualValue = try actualExpression.evaluate() {
9 | var actualGenerator = actualValue.makeIterator()
10 | var lastItem: T?
11 | var item: T?
12 | repeat {
13 | lastItem = item
14 | item = actualGenerator.next()
15 | } while(item != nil)
16 |
17 | return PredicateStatus(bool: lastItem == endingElement)
18 | }
19 | return .fail
20 | }
21 | }
22 |
23 | /// A Nimble matcher that succeeds when the actual collection's last element
24 | /// is equal to the expected object.
25 | public func endWith(_ endingElement: Any) -> Predicate {
26 | return Predicate.simple("end with <\(endingElement)>") { actualExpression in
27 | guard let collection = try actualExpression.evaluate() else { return .fail }
28 | guard collection.count > 0 else { return PredicateStatus(bool: false) }
29 | #if os(Linux)
30 | guard let collectionValue = collection.object(at: collection.count - 1) as? NSObject else {
31 | return .fail
32 | }
33 | #else
34 | let collectionValue = collection.object(at: collection.count - 1) as AnyObject
35 | #endif
36 |
37 | return PredicateStatus(bool: collectionValue.isEqual(endingElement))
38 | }
39 | }
40 |
41 | /// A Nimble matcher that succeeds when the actual string contains the expected substring
42 | /// where the expected substring's location is the actual string's length minus the
43 | /// expected substring's length.
44 | public func endWith(_ endingSubstring: String) -> Predicate {
45 | return Predicate.simple("end with <\(endingSubstring)>") { actualExpression in
46 | if let collection = try actualExpression.evaluate() {
47 | return PredicateStatus(bool: collection.hasSuffix(endingSubstring))
48 | }
49 | return .fail
50 | }
51 | }
52 |
53 | #if canImport(Darwin)
54 | extension NMBObjCMatcher {
55 | @objc public class func endWithMatcher(_ expected: Any) -> NMBMatcher {
56 | return NMBPredicate { actualExpression in
57 | let actual = try actualExpression.evaluate()
58 | if actual is String {
59 | let expr = actualExpression.cast { $0 as? String }
60 | // swiftlint:disable:next force_cast
61 | return try endWith(expected as! String).satisfies(expr).toObjectiveC()
62 | } else {
63 | let expr = actualExpression.cast { $0 as? NMBOrderedCollection }
64 | return try endWith(expected).satisfies(expr).toObjectiveC()
65 | }
66 | }
67 | }
68 | }
69 | #endif
70 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/HaveCount.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // The `haveCount` matchers do not print the full string representation of the collection value,
4 | // instead they only print the type name and the expected count. This makes it easier to understand
5 | // the reason for failed expectations. See: https://github.com/Quick/Nimble/issues/308.
6 | // The representation of the collection content is provided in a new line as an `extendedMessage`.
7 |
8 | /// A Nimble matcher that succeeds when the actual Collection's count equals
9 | /// the expected value
10 | public func haveCount(_ expectedValue: Int) -> Predicate {
11 | return Predicate.define { actualExpression in
12 | if let actualValue = try actualExpression.evaluate() {
13 | let message = ExpectationMessage
14 | .expectedCustomValueTo(
15 | "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
16 | "\(actualValue.count)"
17 | )
18 | .appended(details: "Actual Value: \(stringify(actualValue))")
19 |
20 | let result = expectedValue == actualValue.count
21 | return PredicateResult(bool: result, message: message)
22 | } else {
23 | return PredicateResult(status: .fail, message: .fail(""))
24 | }
25 | }
26 | }
27 |
28 | /// A Nimble matcher that succeeds when the actual collection's count equals
29 | /// the expected value
30 | public func haveCount(_ expectedValue: Int) -> Predicate {
31 | return Predicate { actualExpression in
32 | if let actualValue = try actualExpression.evaluate() {
33 | let message = ExpectationMessage
34 | .expectedCustomValueTo(
35 | "have \(prettyCollectionType(actualValue)) with count \(stringify(expectedValue))",
36 | "\(actualValue.count)"
37 | )
38 | .appended(details: "Actual Value: \(stringify(actualValue))")
39 |
40 | let result = expectedValue == actualValue.count
41 | return PredicateResult(bool: result, message: message)
42 | } else {
43 | return PredicateResult(status: .fail, message: .fail(""))
44 | }
45 | }
46 | }
47 |
48 | #if canImport(Darwin)
49 | extension NMBObjCMatcher {
50 | @objc public class func haveCountMatcher(_ expected: NSNumber) -> NMBMatcher {
51 | return NMBPredicate { actualExpression in
52 | let location = actualExpression.location
53 | let actualValue = try actualExpression.evaluate()
54 | if let value = actualValue as? NMBCollection {
55 | let expr = Expression(expression: ({ value as NMBCollection}), location: location)
56 | return try haveCount(expected.intValue).satisfies(expr).toObjectiveC()
57 | }
58 |
59 | let message: ExpectationMessage
60 | if let actualValue = actualValue {
61 | message = ExpectationMessage.expectedCustomValueTo(
62 | "get type of NSArray, NSSet, NSDictionary, or NSHashTable",
63 | "\(String(describing: type(of: actualValue)))"
64 | )
65 | } else {
66 | message = ExpectationMessage
67 | .expectedActualValueTo("have a collection with count \(stringify(expected.intValue))")
68 | .appendedBeNilHint()
69 | }
70 | return NMBPredicateResult(status: .fail, message: message.toObjectiveC())
71 | }
72 | }
73 | }
74 | #endif
75 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/Match.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual string satisfies the regular expression
4 | /// described by the expected string.
5 | public func match(_ expectedValue: String?) -> Predicate {
6 | return Predicate.simple("match <\(stringify(expectedValue))>") { actualExpression in
7 | if let actual = try actualExpression.evaluate() {
8 | if let regexp = expectedValue {
9 | let bool = actual.range(of: regexp, options: .regularExpression) != nil
10 | return PredicateStatus(bool: bool)
11 | }
12 | }
13 |
14 | return .fail
15 | }
16 | }
17 |
18 | #if canImport(Darwin)
19 |
20 | extension NMBObjCMatcher {
21 | @objc public class func matchMatcher(_ expected: NSString) -> NMBMatcher {
22 | return NMBPredicate { actualExpression in
23 | let actual = actualExpression.cast { $0 as? String }
24 | return try match(expected.description).satisfies(actual).toObjectiveC()
25 | }
26 | }
27 | }
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/MatchError.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual expression evaluates to an
4 | /// error from the specified case.
5 | ///
6 | /// Errors are tried to be compared by their implementation of Equatable,
7 | /// otherwise they fallback to comparison by _domain and _code.
8 | public func matchError(_ error: T) -> Predicate {
9 | return Predicate.define { actualExpression in
10 | let actualError = try actualExpression.evaluate()
11 |
12 | let failureMessage = FailureMessage()
13 | setFailureMessageForError(
14 | failureMessage,
15 | postfixMessageVerb: "match",
16 | actualError: actualError,
17 | error: error
18 | )
19 |
20 | var matches = false
21 | if let actualError = actualError, errorMatchesExpectedError(actualError, expectedError: error) {
22 | matches = true
23 | }
24 |
25 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
26 | }
27 | }
28 |
29 | /// A Nimble matcher that succeeds when the actual expression evaluates to an
30 | /// error from the specified case.
31 | ///
32 | /// Errors are tried to be compared by their implementation of Equatable,
33 | /// otherwise they fallback to comparision by _domain and _code.
34 | public func matchError(_ error: T) -> Predicate {
35 | return Predicate.define { actualExpression in
36 | let actualError = try actualExpression.evaluate()
37 |
38 | let failureMessage = FailureMessage()
39 | setFailureMessageForError(
40 | failureMessage,
41 | postfixMessageVerb: "match",
42 | actualError: actualError,
43 | error: error
44 | )
45 |
46 | var matches = false
47 | if let actualError = actualError as? T, error == actualError {
48 | matches = true
49 | }
50 |
51 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
52 | }
53 | }
54 |
55 | /// A Nimble matcher that succeeds when the actual expression evaluates to an
56 | /// error of the specified type
57 | public func matchError(_ errorType: T.Type) -> Predicate {
58 | return Predicate.define { actualExpression in
59 | let actualError = try actualExpression.evaluate()
60 |
61 | let failureMessage = FailureMessage()
62 | setFailureMessageForError(
63 | failureMessage,
64 | postfixMessageVerb: "match",
65 | actualError: actualError,
66 | errorType: errorType
67 | )
68 |
69 | var matches = false
70 | if actualError as? T != nil {
71 | matches = true
72 | }
73 |
74 | return PredicateResult(bool: matches, message: failureMessage.toExpectationMessage())
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift:
--------------------------------------------------------------------------------
1 | /// DEPRECATED: A convenience API to build matchers that don't need special negation
2 | /// behavior. The toNot() behavior is the negation of to().
3 | ///
4 | /// @see NonNilMatcherFunc if you prefer to have this matcher fail when nil
5 | /// values are received in an expectation.
6 | ///
7 | /// You may use this when implementing your own custom matchers.
8 | ///
9 | /// Use the Matcher protocol instead of this type to accept custom matchers as
10 | /// input parameters.
11 | /// @see allPass for an example that uses accepts other matchers as input.
12 | @available(*, deprecated, message: "Use to Predicate instead")
13 | public struct MatcherFunc: Matcher {
14 | public let matcher: (Expression, FailureMessage) throws -> Bool
15 |
16 | public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) {
17 | self.matcher = matcher
18 | }
19 |
20 | public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool {
21 | return try matcher(actualExpression, failureMessage)
22 | }
23 |
24 | public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool {
25 | return try !matcher(actualExpression, failureMessage)
26 | }
27 |
28 | /// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one.
29 | /// Note: You should definitely spend the time to convert to the new api as soon as possible
30 | /// since this struct type is deprecated.
31 | public var predicate: Predicate {
32 | return Predicate.fromDeprecatedMatcher(self)
33 | }
34 | }
35 |
36 | /// DEPRECATED: A convenience API to build matchers that don't need special negation
37 | /// behavior. The toNot() behavior is the negation of to().
38 | ///
39 | /// Unlike MatcherFunc, this will always fail if an expectation contains nil.
40 | /// This applies regardless of using to() or toNot().
41 | ///
42 | /// You may use this when implementing your own custom matchers.
43 | ///
44 | /// Use the Matcher protocol instead of this type to accept custom matchers as
45 | /// input parameters.
46 | /// @see allPass for an example that uses accepts other matchers as input.
47 | @available(*, deprecated, message: "Use to Predicate instead")
48 | public struct NonNilMatcherFunc: Matcher {
49 | public let matcher: (Expression, FailureMessage) throws -> Bool
50 |
51 | public init(_ matcher: @escaping (Expression, FailureMessage) throws -> Bool) {
52 | self.matcher = matcher
53 | }
54 |
55 | public func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool {
56 | let pass = try matcher(actualExpression, failureMessage)
57 | if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) {
58 | return false
59 | }
60 | return pass
61 | }
62 |
63 | public func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool {
64 | let pass = try !matcher(actualExpression, failureMessage)
65 | if try attachNilErrorIfNeeded(actualExpression, failureMessage: failureMessage) {
66 | return false
67 | }
68 | return pass
69 | }
70 |
71 | internal func attachNilErrorIfNeeded(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool {
72 | if try actualExpression.evaluate() == nil {
73 | failureMessage.postfixActual = " (use beNil() to match nils)"
74 | return true
75 | }
76 | return false
77 | }
78 |
79 | /// Compatibility layer to new Matcher API. Converts an old-style matcher to a new one.
80 | /// Note: You should definitely spend the time to convert to the new api as soon as possible
81 | /// since this struct type is deprecated.
82 | public var predicate: Predicate {
83 | return Predicate.fromDeprecatedMatcher(self)
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/PostNotification.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | internal class NotificationCollector {
4 | private(set) var observedNotifications: [Notification]
5 | private let notificationCenter: NotificationCenter
6 | private var token: NSObjectProtocol?
7 |
8 | required init(notificationCenter: NotificationCenter) {
9 | self.notificationCenter = notificationCenter
10 | self.observedNotifications = []
11 | }
12 |
13 | func startObserving() {
14 | // swiftlint:disable:next line_length
15 | self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] notification in
16 | // linux-swift gets confused by .append(n)
17 | self?.observedNotifications.append(notification)
18 | }
19 | }
20 |
21 | deinit {
22 | if let token = self.token {
23 | self.notificationCenter.removeObserver(token)
24 | }
25 | }
26 | }
27 |
28 | private let mainThread = pthread_self()
29 |
30 | public func postNotifications(
31 | _ predicate: Predicate<[Notification]>,
32 | fromNotificationCenter center: NotificationCenter = .default
33 | ) -> Predicate {
34 | _ = mainThread // Force lazy-loading of this value
35 | let collector = NotificationCollector(notificationCenter: center)
36 | collector.startObserving()
37 | var once: Bool = false
38 |
39 | return Predicate { actualExpression in
40 | let collectorNotificationsExpression = Expression(
41 | memoizedExpression: { _ in
42 | return collector.observedNotifications
43 | },
44 | location: actualExpression.location,
45 | withoutCaching: true
46 | )
47 |
48 | assert(pthread_equal(mainThread, pthread_self()) != 0, "Only expecting closure to be evaluated on main thread.")
49 | if !once {
50 | once = true
51 | _ = try actualExpression.evaluate()
52 | }
53 |
54 | let actualValue: String
55 | if collector.observedNotifications.isEmpty {
56 | actualValue = "no notifications"
57 | } else {
58 | actualValue = "<\(stringify(collector.observedNotifications))>"
59 | }
60 |
61 | var result = try predicate.satisfies(collectorNotificationsExpression)
62 | result.message = result.message.replacedExpectation { message in
63 | return .expectedCustomValueTo(message.expectedMessage, actualValue)
64 | }
65 | return result
66 | }
67 | }
68 |
69 | public func postNotifications(
70 | _ notificationsMatcher: T,
71 | fromNotificationCenter center: NotificationCenter = .default)
72 | -> Predicate
73 | where T: Matcher, T.ValueType == [Notification]
74 | {
75 | _ = mainThread // Force lazy-loading of this value
76 | let collector = NotificationCollector(notificationCenter: center)
77 | collector.startObserving()
78 | var once: Bool = false
79 |
80 | return Predicate { actualExpression in
81 | let collectorNotificationsExpression = Expression(memoizedExpression: { _ in
82 | return collector.observedNotifications
83 | }, location: actualExpression.location, withoutCaching: true)
84 |
85 | assert(pthread_equal(mainThread, pthread_self()) != 0, "Only expecting closure to be evaluated on main thread.")
86 | if !once {
87 | once = true
88 | _ = try actualExpression.evaluate()
89 | }
90 |
91 | let failureMessage = FailureMessage()
92 | let match = try notificationsMatcher.matches(collectorNotificationsExpression, failureMessage: failureMessage)
93 | if collector.observedNotifications.isEmpty {
94 | failureMessage.actualValue = "no notifications"
95 | } else {
96 | failureMessage.actualValue = "<\(stringify(collector.observedNotifications))>"
97 | }
98 | return PredicateResult(bool: match, message: failureMessage.toExpectationMessage())
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAllOf.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value matches with all of the matchers
4 | /// provided in the variable list of matchers.
5 | public func satisfyAllOf(_ predicates: Predicate...) -> Predicate {
6 | return satisfyAllOf(predicates)
7 | }
8 |
9 | /// A Nimble matcher that succeeds when the actual value matches with all of the matchers
10 | /// provided in the variable list of matchers.
11 | public func satisfyAllOf(_ matchers: U...) -> Predicate
12 | where U: Matcher, U.ValueType == T {
13 | return satisfyAllOf(matchers.map { $0.predicate })
14 | }
15 |
16 | internal func satisfyAllOf(_ predicates: [Predicate]) -> Predicate {
17 | return Predicate.define { actualExpression in
18 | var postfixMessages = [String]()
19 | var matches = true
20 | for predicate in predicates {
21 | let result = try predicate.satisfies(actualExpression)
22 | if result.toBoolean(expectation: .toNotMatch) {
23 | matches = false
24 | }
25 | postfixMessages.append("{\(result.message.expectedMessage)}")
26 | }
27 |
28 | var msg: ExpectationMessage
29 | if let actualValue = try actualExpression.evaluate() {
30 | msg = .expectedCustomValueTo(
31 | "match all of: " + postfixMessages.joined(separator: ", and "),
32 | "\(actualValue)"
33 | )
34 | } else {
35 | msg = .expectedActualValueTo(
36 | "match all of: " + postfixMessages.joined(separator: ", and ")
37 | )
38 | }
39 |
40 | return PredicateResult(bool: matches, message: msg)
41 | }
42 | }
43 |
44 | public func && (left: Predicate, right: Predicate) -> Predicate {
45 | return satisfyAllOf(left, right)
46 | }
47 |
48 | #if canImport(Darwin)
49 | extension NMBObjCMatcher {
50 | @objc public class func satisfyAllOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
51 | return NMBPredicate { actualExpression in
52 | if matchers.isEmpty {
53 | return NMBPredicateResult(
54 | status: NMBPredicateStatus.fail,
55 | message: NMBExpectationMessage(
56 | fail: "satisfyAllOf must be called with at least one matcher"
57 | )
58 | )
59 | }
60 |
61 | var elementEvaluators = [Predicate]()
62 | for matcher in matchers {
63 | let elementEvaluator = Predicate { expression in
64 | if let predicate = matcher as? NMBPredicate {
65 | // swiftlint:disable:next line_length
66 | return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift()
67 | } else {
68 | let failureMessage = FailureMessage()
69 | let success = matcher.matches(
70 | // swiftlint:disable:next force_try
71 | { try! expression.evaluate() },
72 | failureMessage: failureMessage,
73 | location: actualExpression.location
74 | )
75 | return PredicateResult(bool: success, message: failureMessage.toExpectationMessage())
76 | }
77 | }
78 |
79 | elementEvaluators.append(elementEvaluator)
80 | }
81 |
82 | return try satisfyAllOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
83 | }
84 | }
85 | }
86 | #endif
87 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// A Nimble matcher that succeeds when the actual value matches with any of the matchers
4 | /// provided in the variable list of matchers.
5 | public func satisfyAnyOf(_ predicates: Predicate...) -> Predicate {
6 | return satisfyAnyOf(predicates)
7 | }
8 |
9 | /// A Nimble matcher that succeeds when the actual value matches with any of the matchers
10 | /// provided in the variable list of matchers.
11 | public func satisfyAnyOf(_ matchers: U...) -> Predicate
12 | where U: Matcher, U.ValueType == T {
13 | return satisfyAnyOf(matchers.map { $0.predicate })
14 | }
15 |
16 | internal func satisfyAnyOf(_ predicates: [Predicate]) -> Predicate {
17 | return Predicate.define { actualExpression in
18 | var postfixMessages = [String]()
19 | var matches = false
20 | for predicate in predicates {
21 | let result = try predicate.satisfies(actualExpression)
22 | if result.toBoolean(expectation: .toMatch) {
23 | matches = true
24 | }
25 | postfixMessages.append("{\(result.message.expectedMessage)}")
26 | }
27 |
28 | var msg: ExpectationMessage
29 | if let actualValue = try actualExpression.evaluate() {
30 | msg = .expectedCustomValueTo(
31 | "match one of: " + postfixMessages.joined(separator: ", or "),
32 | "\(actualValue)"
33 | )
34 | } else {
35 | msg = .expectedActualValueTo(
36 | "match one of: " + postfixMessages.joined(separator: ", or ")
37 | )
38 | }
39 |
40 | return PredicateResult(bool: matches, message: msg)
41 | }
42 | }
43 |
44 | public func || (left: Predicate, right: Predicate) -> Predicate {
45 | return satisfyAnyOf(left, right)
46 | }
47 |
48 | public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> Predicate {
49 | return satisfyAnyOf(left, right)
50 | }
51 |
52 | public func || (left: MatcherFunc, right: MatcherFunc) -> Predicate {
53 | return satisfyAnyOf(left, right)
54 | }
55 |
56 | #if canImport(Darwin)
57 | extension NMBObjCMatcher {
58 | @objc public class func satisfyAnyOfMatcher(_ matchers: [NMBMatcher]) -> NMBPredicate {
59 | return NMBPredicate { actualExpression in
60 | if matchers.isEmpty {
61 | return NMBPredicateResult(
62 | status: NMBPredicateStatus.fail,
63 | message: NMBExpectationMessage(
64 | fail: "satisfyAnyOf must be called with at least one matcher"
65 | )
66 | )
67 | }
68 |
69 | var elementEvaluators = [Predicate]()
70 | for matcher in matchers {
71 | let elementEvaluator = Predicate { expression in
72 | if let predicate = matcher as? NMBPredicate {
73 | // swiftlint:disable:next line_length
74 | return predicate.satisfies({ try expression.evaluate() }, location: actualExpression.location).toSwift()
75 | } else {
76 | let failureMessage = FailureMessage()
77 | let success = matcher.matches(
78 | // swiftlint:disable:next force_try
79 | { try! expression.evaluate() },
80 | failureMessage: failureMessage,
81 | location: actualExpression.location
82 | )
83 | return PredicateResult(bool: success, message: failureMessage.toExpectationMessage())
84 | }
85 | }
86 |
87 | elementEvaluators.append(elementEvaluator)
88 | }
89 |
90 | return try satisfyAnyOf(elementEvaluators).satisfies(actualExpression).toObjectiveC()
91 | }
92 | }
93 | }
94 | #endif
95 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public func throwAssertion() -> Predicate {
4 | return Predicate { actualExpression in
5 | #if arch(x86_64) && canImport(Darwin) && !SWIFT_PACKAGE
6 | let message = ExpectationMessage.expectedTo("throw an assertion")
7 |
8 | var actualError: Error?
9 | let caughtException: BadInstructionException? = catchBadInstruction {
10 | #if os(tvOS)
11 | if !NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning {
12 | print()
13 | print("[Nimble Warning]: If you're getting stuck on a debugger breakpoint for a " +
14 | "fatal error while using throwAssertion(), please disable 'Debug Executable' " +
15 | "in your scheme. Go to 'Edit Scheme > Test > Info' and uncheck " +
16 | "'Debug Executable'. If you've already done that, suppress this warning " +
17 | "by setting `NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true`. " +
18 | "This is required because the standard methods of catching assertions " +
19 | "(mach APIs) are unavailable for tvOS. Instead, the same mechanism the " +
20 | "debugger uses is the fallback method for tvOS."
21 | )
22 | print()
23 | NimbleEnvironment.activeInstance.suppressTVOSAssertionWarning = true
24 | }
25 | #endif
26 | do {
27 | try actualExpression.evaluate()
28 | } catch {
29 | actualError = error
30 | }
31 | }
32 |
33 | if let actualError = actualError {
34 | return PredicateResult(
35 | bool: false,
36 | message: message.appended(message: "; threw error instead <\(actualError)>")
37 | )
38 | } else {
39 | return PredicateResult(bool: caughtException != nil, message: message)
40 | }
41 | #elseif SWIFT_PACKAGE
42 | fatalError("The throwAssertion Nimble matcher does not currently support Swift CLI." +
43 | " You can silence this error by placing the test case inside an #if !SWIFT_PACKAGE" +
44 | " conditional statement")
45 | #else
46 | fatalError("The throwAssertion Nimble matcher can only run on x86_64 platforms with " +
47 | "Objective-C (e.g. macOS, iPhone 5s or later simulators). You can silence this error " +
48 | "by placing the test case inside an #if arch(x86_64) or canImport(Darwin) conditional statement")
49 | #endif
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Matchers/ToSucceed.swift:
--------------------------------------------------------------------------------
1 | /**
2 | Used by the `toSucceed` matcher.
3 |
4 | This is the return type for the closure.
5 | */
6 | public enum ToSucceedResult {
7 | case succeeded
8 | case failed(reason: String)
9 | }
10 |
11 | /**
12 | A Nimble matcher that takes in a closure for validation.
13 |
14 | Return `.succeeded` when the validation succeeds.
15 | Return `.failed` with a failure reason when the validation fails.
16 | */
17 | public func succeed() -> Predicate<() -> ToSucceedResult> {
18 | return Predicate.define { actualExpression in
19 | let optActual = try actualExpression.evaluate()
20 | guard let actual = optActual else {
21 | return PredicateResult(status: .fail, message: .fail("expected a closure, got "))
22 | }
23 |
24 | switch actual() {
25 | case .succeeded:
26 | return PredicateResult(
27 | bool: true,
28 | message: .expectedCustomValueTo("succeed", "")
29 | )
30 | case .failed(let reason):
31 | return PredicateResult(
32 | bool: false,
33 | message: .expectedCustomValueTo("succeed", " because <\(reason)>")
34 | )
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Nimble.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "NMBExceptionCapture.h"
3 | #import "NMBStringify.h"
4 | #import "DSL.h"
5 |
6 | #if TARGET_OS_TV
7 | #import "CwlPreconditionTesting_POSIX.h"
8 | #else
9 | #import "CwlPreconditionTesting.h"
10 | #endif
11 |
12 | FOUNDATION_EXPORT double NimbleVersionNumber;
13 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[];
14 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Utils/Errors.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // Generic
4 |
5 | internal func setFailureMessageForError(
6 | _ failureMessage: FailureMessage,
7 | postfixMessageVerb: String = "throw",
8 | actualError: Error?,
9 | error: T? = nil,
10 | errorType: T.Type? = nil,
11 | closure: ((T) -> Void)? = nil) {
12 | failureMessage.postfixMessage = "\(postfixMessageVerb) error"
13 |
14 | if let error = error {
15 | failureMessage.postfixMessage += " <\(error)>"
16 | } else if errorType != nil || closure != nil {
17 | failureMessage.postfixMessage += " from type <\(T.self)>"
18 | }
19 | if closure != nil {
20 | failureMessage.postfixMessage += " that satisfies block"
21 | }
22 | if error == nil && errorType == nil && closure == nil {
23 | failureMessage.postfixMessage = "\(postfixMessageVerb) any error"
24 | }
25 |
26 | if let actualError = actualError {
27 | failureMessage.actualValue = "<\(actualError)>"
28 | } else {
29 | failureMessage.actualValue = "no error"
30 | }
31 | }
32 |
33 | internal func errorMatchesExpectedError(
34 | _ actualError: Error,
35 | expectedError: T) -> Bool {
36 | return actualError._domain == expectedError._domain
37 | && actualError._code == expectedError._code
38 | }
39 |
40 | // Non-generic
41 |
42 | internal func setFailureMessageForError(
43 | _ failureMessage: FailureMessage,
44 | actualError: Error?,
45 | closure: ((Error) -> Void)?) {
46 | failureMessage.postfixMessage = "throw error"
47 |
48 | if closure != nil {
49 | failureMessage.postfixMessage += " that satisfies block"
50 | } else {
51 | failureMessage.postfixMessage = "throw any error"
52 | }
53 |
54 | if let actualError = actualError {
55 | failureMessage.actualValue = "<\(actualError)>"
56 | } else {
57 | failureMessage.actualValue = "no error"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Utils/Functional.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | #if !swift(>=4.2)
4 | extension Sequence {
5 | internal func allSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
6 | for item in self {
7 | if try !predicate(item) {
8 | return false
9 | }
10 | }
11 | return true
12 | }
13 | }
14 | #endif
15 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/Nimble/Utils/SourceLocation.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // Ideally we would always use `StaticString` as the type for tracking the file name
4 | // that expectations originate from, for consistency with `assert` etc. from the
5 | // stdlib, and because recent versions of the XCTest overlay require `StaticString`
6 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on Mac), we
7 | // have to use `String` instead because StaticString can't be generated from Objective-C
8 | #if SWIFT_PACKAGE
9 | public typealias FileString = StaticString
10 | #else
11 | public typealias FileString = String
12 | #endif
13 |
14 | public final class SourceLocation: NSObject {
15 | public let file: FileString
16 | public let line: UInt
17 |
18 | override init() {
19 | file = "Unknown File"
20 | line = 0
21 | }
22 |
23 | init(file: FileString, line: UInt) {
24 | self.file = file
25 | self.line = line
26 | }
27 |
28 | override public var description: String {
29 | return "\(file):\(line)"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface NMBExceptionCapture : NSObject
5 |
6 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally;
7 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock NS_SWIFT_NAME(tryBlock(_:));
8 |
9 | @end
10 |
11 | typedef void(^NMBSourceCallbackBlock)(BOOL successful);
12 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m:
--------------------------------------------------------------------------------
1 | #import "NMBExceptionCapture.h"
2 |
3 | @interface NMBExceptionCapture ()
4 | @property (nonatomic, copy) void(^ _Nullable handler)(NSException * _Nullable);
5 | @property (nonatomic, copy) void(^ _Nullable finally)(void);
6 | @end
7 |
8 | @implementation NMBExceptionCapture
9 |
10 | - (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)(void))finally {
11 | self = [super init];
12 | if (self) {
13 | self.handler = handler;
14 | self.finally = finally;
15 | }
16 | return self;
17 | }
18 |
19 | - (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)(void))unsafeBlock {
20 | @try {
21 | unsafeBlock();
22 | }
23 | @catch (NSException *exception) {
24 | if (self.handler) {
25 | self.handler(exception);
26 | }
27 | }
28 | @finally {
29 | if (self.finally) {
30 | self.finally();
31 | }
32 | }
33 | }
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.h:
--------------------------------------------------------------------------------
1 | @class NSString;
2 |
3 | /**
4 | * Returns a string appropriate for displaying in test output
5 | * from the provided value.
6 | *
7 | * @param anyObject A value that will show up in a test's output.
8 | *
9 | * @return The string that is returned can be
10 | * customized per type by conforming a type to the `TestOutputStringConvertible`
11 | * protocol. When stringifying a non-`TestOutputStringConvertible` type, this
12 | * function will return the value's debug description and then its
13 | * normal description if available and in that order. Otherwise it
14 | * will return the result of constructing a string from the value.
15 | *
16 | * @see `TestOutputStringConvertible`
17 | */
18 | extern NSString *_Nonnull NMBStringify(id _Nullable anyObject) __attribute__((warn_unused_result));
19 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/NimbleObjectiveC/NMBStringify.m:
--------------------------------------------------------------------------------
1 | #import "NMBStringify.h"
2 |
3 | #if __has_include("Nimble-Swift.h")
4 | #import "Nimble-Swift.h"
5 | #else
6 | #import
7 | #endif
8 |
9 | NSString *_Nonnull NMBStringify(id _Nullable anyObject) {
10 | return [NMBStringer stringify:anyObject];
11 | }
12 |
--------------------------------------------------------------------------------
/Pods/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #if __has_include("Nimble-Swift.h")
5 | #import "Nimble-Swift.h"
6 | #else
7 | #import
8 | #endif
9 |
10 | #pragma mark - Method Swizzling
11 |
12 | /// Swaps the implementations between two instance methods.
13 | ///
14 | /// @param class The class containing `originalSelector`.
15 | /// @param originalSelector Original method to replace.
16 | /// @param replacementSelector Replacement method.
17 | void swizzleSelectors(Class class, SEL originalSelector, SEL replacementSelector) {
18 | Method originalMethod = class_getInstanceMethod(class, originalSelector);
19 | Method replacementMethod = class_getInstanceMethod(class, replacementSelector);
20 |
21 | BOOL didAddMethod =
22 | class_addMethod(class,
23 | originalSelector,
24 | method_getImplementation(replacementMethod),
25 | method_getTypeEncoding(replacementMethod));
26 |
27 | if (didAddMethod) {
28 | class_replaceMethod(class,
29 | replacementSelector,
30 | method_getImplementation(originalMethod),
31 | method_getTypeEncoding(originalMethod));
32 | } else {
33 | method_exchangeImplementations(originalMethod, replacementMethod);
34 | }
35 | }
36 |
37 | #pragma mark - Private
38 |
39 | @interface XCTestObservationCenter (Private)
40 | - (void)_addLegacyTestObserver:(id)observer;
41 | @end
42 |
43 | @implementation XCTestObservationCenter (Register)
44 |
45 | /// Uses objc method swizzling to register `CurrentTestCaseTracker` as a test observer. This is necessary
46 | /// because Xcode 7.3 introduced timing issues where if a custom `XCTestObservation` is registered too early
47 | /// it suppresses all console output (generated by `XCTestLog`), breaking any tools that depend on this output.
48 | /// This approach waits to register our custom test observer until XCTest adds its first "legacy" observer,
49 | /// falling back to registering after the first normal observer if this private method ever changes.
50 | + (void)load {
51 | if (class_getInstanceMethod([self class], @selector(_addLegacyTestObserver:))) {
52 | // Swizzle -_addLegacyTestObserver:
53 | swizzleSelectors([self class], @selector(_addLegacyTestObserver:), @selector(NMB_original__addLegacyTestObserver:));
54 | } else {
55 | // Swizzle -addTestObserver:, only if -_addLegacyTestObserver: is not implemented
56 | swizzleSelectors([self class], @selector(addTestObserver:), @selector(NMB_original_addTestObserver:));
57 | }
58 | }
59 |
60 | #pragma mark - Replacement Methods
61 |
62 | /// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added.
63 | - (void)NMB_original__addLegacyTestObserver:(id)observer {
64 | [self NMB_original__addLegacyTestObserver:observer];
65 |
66 | static dispatch_once_t onceToken;
67 | dispatch_once(&onceToken, ^{
68 | [self addTestObserver:[CurrentTestCaseTracker sharedInstance]];
69 | });
70 | }
71 |
72 | /// Registers `CurrentTestCaseTracker` as a test observer after `XCTestLog` has been added.
73 | /// This method is only used if `-_addLegacyTestObserver:` is not impelemented. (added in Xcode 7.3)
74 | - (void)NMB_original_addTestObserver:(id)observer {
75 | [self NMB_original_addTestObserver:observer];
76 |
77 | static dispatch_once_t onceToken;
78 | dispatch_once(&onceToken, ^{
79 | [self NMB_original_addTestObserver:[CurrentTestCaseTracker sharedInstance]];
80 | });
81 | }
82 |
83 | @end
84 |
--------------------------------------------------------------------------------
/Pods/Quick/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](https://travis-ci.org/Quick/Quick)
4 | [](https://cocoapods.org/pods/Quick)
5 | [](https://github.com/Carthage/Carthage)
6 | [](https://cocoapods.org/pods/Quick)
7 | [](https://houndci.com)
8 |
9 | Quick is a behavior-driven development framework for Swift and Objective-C.
10 | Inspired by [RSpec](https://github.com/rspec/rspec), [Specta](https://github.com/specta/specta), and [Ginkgo](https://github.com/onsi/ginkgo).
11 |
12 | 
13 |
14 | ```swift
15 | // Swift
16 |
17 | import Quick
18 | import Nimble
19 |
20 | class TableOfContentsSpec: QuickSpec {
21 | override func spec() {
22 | describe("the 'Documentation' directory") {
23 | it("has everything you need to get started") {
24 | let sections = Directory("Documentation").sections
25 | expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups"))
26 | expect(sections).to(contain("Installing Quick"))
27 | }
28 |
29 | context("if it doesn't have what you're looking for") {
30 | it("needs to be updated") {
31 | let you = You(awesome: true)
32 | expect{you.submittedAnIssue}.toEventually(beTruthy())
33 | }
34 | }
35 | }
36 | }
37 | }
38 | ```
39 | #### Nimble
40 | Quick comes together with [Nimble](https://github.com/Quick/Nimble) — a matcher framework for your tests. You can learn why `XCTAssert()` statements make your expectations unclear and how to fix that using Nimble assertions [here](./Documentation/en-us/NimbleAssertions.md).
41 |
42 | ## Swift Version
43 |
44 | Certain versions of Quick and Nimble only support certain versions of Swift. Depending on which version of Swift your project uses, you should use specific versions of Quick and Nimble. Use the table below to determine which versions of Quick and Nimble are compatible with your project.
45 |
46 | |Swift version |Quick version |Nimble version |
47 | |:--------------------|:---------------|:--------------|
48 | |Swift 4.2 |v1.3.2 or later |v7.3.2 or later|
49 | |Swift 3 / Swift 4 |v1.0.0 or later |v5.0.0 or later|
50 | |Swift 2.2 / Swift 2.3|v0.9.3 |v4.1.0 |
51 |
52 | ## Documentation
53 |
54 | All documentation can be found in the [Documentation folder](./Documentation), including [detailed installation instructions](./Documentation/en-us/InstallingQuick.md) for CocoaPods, Carthage, Git submodules, and more. For example, you can install Quick and [Nimble](https://github.com/Quick/Nimble) using CocoaPods by adding the following to your Podfile:
55 |
56 | ```rb
57 | # Podfile
58 |
59 | use_frameworks!
60 |
61 | target "MyApp" do
62 | # Normal libraries
63 |
64 | abstract_target 'Tests' do
65 | inherit! :search_paths
66 | target "MyAppTests"
67 | target "MyAppUITests"
68 |
69 | pod 'Quick'
70 | pod 'Nimble'
71 | end
72 | end
73 | ```
74 |
75 | ## Projects using Quick
76 |
77 | Over ten-thousand apps use either Quick and Nimble however, as they are not included in the app binary, neither appear in “Top Used Libraries” blog posts. Therefore, it would be greatly appreciated to remind contributors that their efforts are valued by compiling a list of organizations and projects that use them.
78 |
79 | Does your organization or project use Quick and Nimble? If yes, [please add your project to the list](https://github.com/Quick/Quick/wiki/Projects-using-Quick).
80 |
81 | ## Who uses Quick
82 |
83 | Similar to projects using Quick, it would be nice to hear why people use Quick and Nimble. Are there features you love? Are there features that are just okay? Are there some features we have that no one uses?
84 |
85 | Have something positive to say about Quick (or Nimble)? If yes, [provide a testimonial here](https://github.com/Quick/Quick/wiki/Who-uses-Quick).
86 |
87 |
88 | ## License
89 |
90 | Apache 2.0 license. See the [`LICENSE`](LICENSE) file for details.
91 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Behavior.swift:
--------------------------------------------------------------------------------
1 | /**
2 | A `Behavior` encapsulates a set of examples that can be re-used in several locations using the `itBehavesLike` function with a context instance of the generic type.
3 | */
4 |
5 | open class Behavior {
6 |
7 | public static var name: String { return String(describing: self) }
8 | /**
9 | override this method in your behavior to define a set of reusable examples.
10 |
11 | This behaves just like an example group defines using `describe` or `context`--it may contain any number of `beforeEach`
12 | and `afterEach` closures, as well as any number of examples (defined using `it`).
13 |
14 | - parameter aContext: A closure that, when evaluated, returns a `Context` instance that provide the information on the subject.
15 | */
16 | open class func spec(_ aContext: @escaping () -> Context) {}
17 | }
18 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Callsite.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | #if canImport(Darwin) && !SWIFT_PACKAGE
4 | @objcMembers
5 | public class _CallsiteBase: NSObject {}
6 | #else
7 | public class _CallsiteBase: NSObject {}
8 | #endif
9 |
10 | // Ideally we would always use `StaticString` as the type for tracking the file name
11 | // in which an example is defined, for consistency with `assert` etc. from the
12 | // stdlib, and because recent versions of the XCTest overlay require `StaticString`
13 | // when calling `XCTFail`. Under the Objective-C runtime (i.e. building on macOS), we
14 | // have to use `String` instead because StaticString can't be generated from Objective-C
15 | #if SWIFT_PACKAGE
16 | public typealias FileString = StaticString
17 | #else
18 | public typealias FileString = String
19 | #endif
20 |
21 | /**
22 | An object encapsulating the file and line number at which
23 | a particular example is defined.
24 | */
25 | final public class Callsite: _CallsiteBase {
26 | /**
27 | The absolute path of the file in which an example is defined.
28 | */
29 | public let file: FileString
30 |
31 | /**
32 | The line number on which an example is defined.
33 | */
34 | public let line: UInt
35 |
36 | internal init(file: FileString, line: UInt) {
37 | self.file = file
38 | self.line = line
39 | }
40 | }
41 |
42 | extension Callsite {
43 | /**
44 | Returns a boolean indicating whether two Callsite objects are equal.
45 | If two callsites are in the same file and on the same line, they must be equal.
46 | */
47 | @nonobjc public static func == (lhs: Callsite, rhs: Callsite) -> Bool {
48 | return String(describing: lhs.file) == String(describing: rhs.file) && lhs.line == rhs.line
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/ErrorUtility.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | internal func raiseError(_ message: String) -> Never {
4 | #if canImport(Darwin)
5 | NSException(name: .internalInconsistencyException, reason: message, userInfo: nil).raise()
6 | #endif
7 |
8 | // This won't be reached when ObjC is available and the exception above is raisd
9 | fatalError(message)
10 | }
11 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/ExampleGroup.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /**
4 | Example groups are logical groupings of examples, defined with
5 | the `describe` and `context` functions. Example groups can share
6 | setup and teardown code.
7 | */
8 | final public class ExampleGroup: NSObject {
9 | weak internal var parent: ExampleGroup?
10 | internal let hooks = ExampleHooks()
11 |
12 | internal var phase: HooksPhase = .nothingExecuted
13 |
14 | private let internalDescription: String
15 | private let flags: FilterFlags
16 | private let isInternalRootExampleGroup: Bool
17 | private var childGroups = [ExampleGroup]()
18 | private var childExamples = [Example]()
19 |
20 | internal init(description: String, flags: FilterFlags, isInternalRootExampleGroup: Bool = false) {
21 | self.internalDescription = description
22 | self.flags = flags
23 | self.isInternalRootExampleGroup = isInternalRootExampleGroup
24 | }
25 |
26 | public override var description: String {
27 | return internalDescription
28 | }
29 |
30 | /**
31 | Returns a list of examples that belong to this example group,
32 | or to any of its descendant example groups.
33 | */
34 | public var examples: [Example] {
35 | return childExamples + childGroups.flatMap { $0.examples }
36 | }
37 |
38 | internal var name: String? {
39 | guard let parent = parent else {
40 | return isInternalRootExampleGroup ? nil : description
41 | }
42 |
43 | guard let name = parent.name else { return description }
44 | return "\(name), \(description)"
45 | }
46 |
47 | internal var filterFlags: FilterFlags {
48 | var aggregateFlags = flags
49 | walkUp { group in
50 | for (key, value) in group.flags {
51 | aggregateFlags[key] = value
52 | }
53 | }
54 | return aggregateFlags
55 | }
56 |
57 | internal var befores: [BeforeExampleWithMetadataClosure] {
58 | var closures = Array(hooks.befores.reversed())
59 | walkUp { group in
60 | closures.append(contentsOf: Array(group.hooks.befores.reversed()))
61 | }
62 | return Array(closures.reversed())
63 | }
64 |
65 | internal var afters: [AfterExampleWithMetadataClosure] {
66 | var closures = hooks.afters
67 | walkUp { group in
68 | closures.append(contentsOf: group.hooks.afters)
69 | }
70 | return closures
71 | }
72 |
73 | internal func walkDownExamples(_ callback: (_ example: Example) -> Void) {
74 | for example in childExamples {
75 | callback(example)
76 | }
77 | for group in childGroups {
78 | group.walkDownExamples(callback)
79 | }
80 | }
81 |
82 | internal func appendExampleGroup(_ group: ExampleGroup) {
83 | group.parent = self
84 | childGroups.append(group)
85 | }
86 |
87 | internal func appendExample(_ example: Example) {
88 | example.group = self
89 | childExamples.append(example)
90 | }
91 |
92 | private func walkUp(_ callback: (_ group: ExampleGroup) -> Void) {
93 | var group = self
94 | while let parent = group.parent {
95 | callback(parent)
96 | group = parent
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/ExampleMetadata.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | #if canImport(Darwin) && !SWIFT_PACKAGE
4 | @objcMembers
5 | public class _ExampleMetadataBase: NSObject {}
6 | #else
7 | public class _ExampleMetadataBase: NSObject {}
8 | #endif
9 |
10 | /**
11 | A class that encapsulates information about an example,
12 | including the index at which the example was executed, as
13 | well as the example itself.
14 | */
15 | final public class ExampleMetadata: _ExampleMetadataBase {
16 | /**
17 | The example for which this metadata was collected.
18 | */
19 | public let example: Example
20 |
21 | /**
22 | The index at which this example was executed in the
23 | test suite.
24 | */
25 | public let exampleIndex: Int
26 |
27 | internal init(example: Example, exampleIndex: Int) {
28 | self.example = example
29 | self.exampleIndex = exampleIndex
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Filter.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | #if canImport(Darwin) && !SWIFT_PACKAGE
4 | @objcMembers
5 | public class _FilterBase: NSObject {}
6 | #else
7 | public class _FilterBase: NSObject {}
8 | #endif
9 |
10 | /**
11 | A mapping of string keys to booleans that can be used to
12 | filter examples or example groups. For example, a "focused"
13 | example would have the flags [Focused: true].
14 | */
15 | public typealias FilterFlags = [String: Bool]
16 |
17 | /**
18 | A namespace for filter flag keys, defined primarily to make the
19 | keys available in Objective-C.
20 | */
21 | final public class Filter: _FilterBase {
22 | /**
23 | Example and example groups with [Focused: true] are included in test runs,
24 | excluding all other examples without this flag. Use this to only run one or
25 | two tests that you're currently focusing on.
26 | */
27 | public class var focused: String {
28 | return "focused"
29 | }
30 |
31 | /**
32 | Example and example groups with [Pending: true] are excluded from test runs.
33 | Use this to temporarily suspend examples that you know do not pass yet.
34 | */
35 | public class var pending: String {
36 | return "pending"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Hooks/Closures.swift:
--------------------------------------------------------------------------------
1 | // MARK: Example Hooks
2 |
3 | /**
4 | A closure executed before an example is run.
5 | */
6 | public typealias BeforeExampleClosure = () -> Void
7 |
8 | /**
9 | A closure executed before an example is run. The closure is given example metadata,
10 | which contains information about the example that is about to be run.
11 | */
12 | public typealias BeforeExampleWithMetadataClosure = (_ exampleMetadata: ExampleMetadata) -> Void
13 |
14 | /**
15 | A closure executed after an example is run.
16 | */
17 | public typealias AfterExampleClosure = BeforeExampleClosure
18 |
19 | /**
20 | A closure executed after an example is run. The closure is given example metadata,
21 | which contains information about the example that has just finished running.
22 | */
23 | public typealias AfterExampleWithMetadataClosure = BeforeExampleWithMetadataClosure
24 |
25 | // MARK: Suite Hooks
26 |
27 | /**
28 | A closure executed before any examples are run.
29 | */
30 | public typealias BeforeSuiteClosure = () -> Void
31 |
32 | /**
33 | A closure executed after all examples have finished running.
34 | */
35 | public typealias AfterSuiteClosure = BeforeSuiteClosure
36 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Hooks/ExampleHooks.swift:
--------------------------------------------------------------------------------
1 | /**
2 | A container for closures to be executed before and after each example.
3 | */
4 | final internal class ExampleHooks {
5 | internal var befores: [BeforeExampleWithMetadataClosure] = []
6 | internal var afters: [AfterExampleWithMetadataClosure] = []
7 | internal var phase: HooksPhase = .nothingExecuted
8 |
9 | internal func appendBefore(_ closure: @escaping BeforeExampleWithMetadataClosure) {
10 | befores.append(closure)
11 | }
12 |
13 | internal func appendBefore(_ closure: @escaping BeforeExampleClosure) {
14 | befores.append { (_: ExampleMetadata) in closure() }
15 | }
16 |
17 | internal func appendAfter(_ closure: @escaping AfterExampleWithMetadataClosure) {
18 | afters.append(closure)
19 | }
20 |
21 | internal func appendAfter(_ closure: @escaping AfterExampleClosure) {
22 | afters.append { (_: ExampleMetadata) in closure() }
23 | }
24 |
25 | internal func executeBefores(_ exampleMetadata: ExampleMetadata) {
26 | phase = .beforesExecuting
27 | for before in befores {
28 | before(exampleMetadata)
29 | }
30 |
31 | phase = .beforesFinished
32 | }
33 |
34 | internal func executeAfters(_ exampleMetadata: ExampleMetadata) {
35 | phase = .aftersExecuting
36 | for after in afters {
37 | after(exampleMetadata)
38 | }
39 |
40 | phase = .aftersFinished
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Hooks/HooksPhase.swift:
--------------------------------------------------------------------------------
1 | /**
2 | A description of the execution cycle of the current example with
3 | respect to the hooks of that example.
4 | */
5 | internal enum HooksPhase {
6 | case nothingExecuted
7 | case beforesExecuting
8 | case beforesFinished
9 | case aftersExecuting
10 | case aftersFinished
11 | }
12 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/Hooks/SuiteHooks.swift:
--------------------------------------------------------------------------------
1 | /**
2 | A container for closures to be executed before and after all examples.
3 | */
4 | final internal class SuiteHooks {
5 | internal var befores: [BeforeSuiteClosure] = []
6 | internal var afters: [AfterSuiteClosure] = []
7 | internal var phase: HooksPhase = .nothingExecuted
8 |
9 | internal func appendBefore(_ closure: @escaping BeforeSuiteClosure) {
10 | befores.append(closure)
11 | }
12 |
13 | internal func appendAfter(_ closure: @escaping AfterSuiteClosure) {
14 | afters.append(closure)
15 | }
16 |
17 | internal func executeBefores() {
18 | phase = .beforesExecuting
19 | for before in befores {
20 | before()
21 | }
22 | phase = .beforesFinished
23 | }
24 |
25 | internal func executeAfters() {
26 | phase = .aftersExecuting
27 | for after in afters {
28 | after()
29 | }
30 | phase = .aftersFinished
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift:
--------------------------------------------------------------------------------
1 | #if canImport(Darwin)
2 |
3 | import Foundation
4 |
5 | extension Bundle {
6 |
7 | /**
8 | Locates the first bundle with a '.xctest' file extension.
9 | */
10 | internal static var currentTestBundle: Bundle? {
11 | return allBundles.first { $0.bundlePath.hasSuffix(".xctest") }
12 | }
13 |
14 | /**
15 | Return the module name of the bundle.
16 | Uses the bundle filename and transform it to match Xcode's transformation.
17 | Module name has to be a valid "C99 extended identifier".
18 | */
19 | internal var moduleName: String {
20 | let fileName = bundleURL.fileName
21 | return fileName.c99ExtendedIdentifier
22 | }
23 | }
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift:
--------------------------------------------------------------------------------
1 | #if canImport(Darwin)
2 | import Foundation
3 |
4 | /**
5 | Responsible for building a "Selected tests" suite. This corresponds to a single
6 | spec, and all its examples.
7 | */
8 | internal class QuickSelectedTestSuiteBuilder: QuickTestSuiteBuilder {
9 |
10 | /**
11 | The test spec class to run.
12 | */
13 | let testCaseClass: AnyClass!
14 |
15 | /**
16 | For Objective-C classes, returns the class name. For Swift classes without,
17 | an explicit Objective-C name, returns a module-namespaced class name
18 | (e.g., "FooTests.FooSpec").
19 | */
20 | var testSuiteClassName: String {
21 | return NSStringFromClass(testCaseClass)
22 | }
23 |
24 | /**
25 | Given a test case name:
26 |
27 | FooSpec/testFoo
28 |
29 | Optionally constructs a test suite builder for the named test case class
30 | in the running test bundle.
31 |
32 | If no test bundle can be found, or the test case class can't be found,
33 | initialization fails and returns `nil`.
34 | */
35 | init?(forTestCaseWithName name: String) {
36 | guard let testCaseClass = testCaseClassForTestCaseWithName(name) else {
37 | self.testCaseClass = nil
38 | return nil
39 | }
40 |
41 | self.testCaseClass = testCaseClass
42 | }
43 |
44 | /**
45 | Returns a `QuickTestSuite` that runs the associated test case class.
46 | */
47 | func buildTestSuite() -> QuickTestSuite {
48 | return QuickTestSuite(forTestCaseClass: testCaseClass)
49 | }
50 |
51 | }
52 |
53 | /**
54 | Searches `Bundle.allBundles()` for an xctest bundle, then looks up the named
55 | test case class in that bundle.
56 |
57 | Returns `nil` if a bundle or test case class cannot be found.
58 | */
59 | private func testCaseClassForTestCaseWithName(_ name: String) -> AnyClass? {
60 | func extractClassName(_ name: String) -> String? {
61 | return name.components(separatedBy: "/").first
62 | }
63 |
64 | guard let className = extractClassName(name) else { return nil }
65 | guard let bundle = Bundle.currentTestBundle else { return nil }
66 |
67 | if let testCaseClass = bundle.classNamed(className) { return testCaseClass }
68 |
69 | let moduleName = bundle.moduleName
70 |
71 | return NSClassFromString("\(moduleName).\(className)")
72 | }
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/QuickTestSuite.swift:
--------------------------------------------------------------------------------
1 | #if canImport(Darwin)
2 |
3 | import XCTest
4 |
5 | /**
6 | This protocol defines the role of an object that builds test suites.
7 | */
8 | internal protocol QuickTestSuiteBuilder {
9 |
10 | /**
11 | Construct a `QuickTestSuite` instance with the appropriate test cases added as tests.
12 |
13 | Subsequent calls to this method should return equivalent test suites.
14 | */
15 | func buildTestSuite() -> QuickTestSuite
16 |
17 | }
18 |
19 | /**
20 | A base class for a class cluster of Quick test suites, that should correctly
21 | build dynamic test suites for XCTest to execute.
22 | */
23 | public class QuickTestSuite: XCTestSuite {
24 |
25 | private static var builtTestSuites: Set = Set()
26 |
27 | /**
28 | Construct a test suite for a specific, selected subset of test cases (rather
29 | than the default, which as all test cases).
30 |
31 | If this method is called multiple times for the same test case class, e.g..
32 |
33 | FooSpec/testFoo
34 | FooSpec/testBar
35 |
36 | It is expected that the first call should return a valid test suite, and
37 | all subsequent calls should return `nil`.
38 | */
39 | @objc
40 | public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? {
41 | guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil }
42 |
43 | let (inserted, _) = builtTestSuites.insert(builder.testSuiteClassName)
44 | if inserted {
45 | return builder.buildTestSuite()
46 | } else {
47 | return nil
48 | }
49 | }
50 | }
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/String+C99ExtendedIdentifier.swift:
--------------------------------------------------------------------------------
1 | #if canImport(Darwin)
2 | import Foundation
3 |
4 | extension String {
5 | private static var invalidCharacters: CharacterSet = {
6 | var invalidCharacters = CharacterSet()
7 |
8 | let invalidCharacterSets: [CharacterSet] = [
9 | .whitespacesAndNewlines,
10 | .illegalCharacters,
11 | .controlCharacters,
12 | .punctuationCharacters,
13 | .nonBaseCharacters,
14 | .symbols
15 | ]
16 |
17 | for invalidSet in invalidCharacterSets {
18 | invalidCharacters.formUnion(invalidSet)
19 | }
20 |
21 | return invalidCharacters
22 | }()
23 |
24 | internal var c99ExtendedIdentifier: String {
25 | let validComponents = components(separatedBy: String.invalidCharacters)
26 | let result = validComponents.joined(separator: "_")
27 |
28 | return result.isEmpty ? "_" : result
29 | }
30 | }
31 |
32 | /// Extension methods or properties for NSObject subclasses are invisible from
33 | /// the Objective-C runtime on static linking unless the consumers add `-ObjC`
34 | /// linker flag, so let's make a wrapper class to mitigate that situation.
35 | ///
36 | /// See: https://github.com/Quick/Quick/issues/785 and https://github.com/Quick/Quick/pull/803
37 | @objc
38 | class QCKObjCStringUtils: NSObject {
39 | override private init() {}
40 |
41 | @objc
42 | static func c99ExtendedIdentifier(from string: String) -> String {
43 | return string.c99ExtendedIdentifier
44 | }
45 | }
46 | #endif
47 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/Quick/URL+FileName.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | extension URL {
4 |
5 | /**
6 | Returns the path file name without file extension.
7 | */
8 | var fileName: String {
9 | return self.deletingPathExtension().lastPathComponent
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @class Configuration;
4 |
5 | /**
6 | Subclass QuickConfiguration and override the +[QuickConfiguration configure:]
7 | method in order to configure how Quick behaves when running specs, or to define
8 | shared examples that are used across spec files.
9 | */
10 | @interface QuickConfiguration : NSObject
11 |
12 | /**
13 | This method is executed on each subclass of this class before Quick runs
14 | any examples. You may override this method on as many subclasses as you like, but
15 | there is no guarantee as to the order in which these methods are executed.
16 |
17 | You can override this method in order to:
18 |
19 | 1. Configure how Quick behaves, by modifying properties on the Configuration object.
20 | Setting the same properties in several methods has undefined behavior.
21 |
22 | 2. Define shared examples using `sharedExamples`.
23 |
24 | @param configuration A mutable object that is used to configure how Quick behaves on
25 | a framework level. For details on all the options, see the
26 | documentation in Configuration.swift.
27 | */
28 | + (void)configure:(Configuration *)configuration;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m:
--------------------------------------------------------------------------------
1 | #import "QuickConfiguration.h"
2 | #import
3 |
4 | #if __has_include("Quick-Swift.h")
5 | #import "Quick-Swift.h"
6 | #else
7 | #import
8 | #endif
9 |
10 | typedef void (^QCKClassEnumerationBlock)(Class klass);
11 |
12 | /**
13 | Finds all direct subclasses of the given class and passes them to the block provided.
14 | The classes are iterated over in the order that objc_getClassList returns them.
15 |
16 | @param klass The base class to find subclasses of.
17 | @param block A block that takes a Class. This block will be executed once for each subclass of klass.
18 | */
19 | void qck_enumerateSubclasses(Class klass, QCKClassEnumerationBlock block) {
20 | Class *classes = NULL;
21 | int classesCount = objc_getClassList(NULL, 0);
22 |
23 | if (classesCount > 0) {
24 | classes = (Class *)calloc(sizeof(Class), classesCount);
25 | classesCount = objc_getClassList(classes, classesCount);
26 |
27 | Class subclass, superclass;
28 | for(int i = 0; i < classesCount; i++) {
29 | subclass = classes[i];
30 | superclass = class_getSuperclass(subclass);
31 | if (superclass == klass && block) {
32 | block(subclass);
33 | }
34 | }
35 |
36 | free(classes);
37 | }
38 | }
39 |
40 | @implementation QuickConfiguration
41 |
42 | #pragma mark - Object Lifecycle
43 |
44 | /**
45 | QuickConfiguration is not meant to be instantiated; it merely provides a hook
46 | for users to configure how Quick behaves. Raise an exception if an instance of
47 | QuickConfiguration is created.
48 | */
49 | - (instancetype)init {
50 | NSString *className = NSStringFromClass([self class]);
51 | NSString *selectorName = NSStringFromSelector(@selector(configure:));
52 | [NSException raise:NSInternalInconsistencyException
53 | format:@"%@ is not meant to be instantiated; "
54 | @"subclass %@ and override %@ to configure Quick.",
55 | className, className, selectorName];
56 | return nil;
57 | }
58 |
59 | #pragma mark - NSObject Overrides
60 |
61 | /**
62 | Hook into when QuickConfiguration is initialized in the runtime in order to
63 | call +[QuickConfiguration configure:] on each of its subclasses.
64 | */
65 | + (void)initialize {
66 | // Only enumerate over the subclasses of QuickConfiguration, not any of its subclasses.
67 | if ([self class] == [QuickConfiguration class]) {
68 |
69 | // Only enumerate over subclasses once, even if +[QuickConfiguration initialize]
70 | // were to be called several times. This is necessary because +[QuickSpec initialize]
71 | // manually calls +[QuickConfiguration initialize].
72 | static dispatch_once_t onceToken;
73 | dispatch_once(&onceToken, ^{
74 | qck_enumerateSubclasses([QuickConfiguration class], ^(__unsafe_unretained Class klass) {
75 | [[World sharedWorld] configure:^(Configuration *configuration) {
76 | [klass configure:configuration];
77 | }];
78 | });
79 | [[World sharedWorld] finalizeConfiguration];
80 | });
81 | }
82 | }
83 |
84 | #pragma mark - Public Interface
85 |
86 | + (void)configure:(Configuration *)configuration { }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m:
--------------------------------------------------------------------------------
1 | #import "QCKDSL.h"
2 |
3 | #if __has_include("Quick-Swift.h")
4 | #import "Quick-Swift.h"
5 | #else
6 | #import
7 | #endif
8 |
9 | void qck_beforeSuite(QCKDSLEmptyBlock closure) {
10 | [[World sharedWorld] beforeSuite:closure];
11 | }
12 |
13 | void qck_afterSuite(QCKDSLEmptyBlock closure) {
14 | [[World sharedWorld] afterSuite:closure];
15 | }
16 |
17 | void qck_sharedExamples(NSString *name, QCKDSLSharedExampleBlock closure) {
18 | [[World sharedWorld] sharedExamples:name closure:closure];
19 | }
20 |
21 | void qck_describe(NSString *description, QCKDSLEmptyBlock closure) {
22 | [[World sharedWorld] describe:description flags:@{} closure:closure];
23 | }
24 |
25 | void qck_context(NSString *description, QCKDSLEmptyBlock closure) {
26 | qck_describe(description, closure);
27 | }
28 |
29 | void qck_beforeEach(QCKDSLEmptyBlock closure) {
30 | [[World sharedWorld] beforeEach:closure];
31 | }
32 |
33 | void qck_beforeEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
34 | [[World sharedWorld] beforeEachWithMetadata:closure];
35 | }
36 |
37 | void qck_afterEach(QCKDSLEmptyBlock closure) {
38 | [[World sharedWorld] afterEach:closure];
39 | }
40 |
41 | void qck_afterEachWithMetadata(QCKDSLExampleMetadataBlock closure) {
42 | [[World sharedWorld] afterEachWithMetadata:closure];
43 | }
44 |
45 | QCKItBlock qck_it_builder(NSDictionary *flags, NSString *file, NSUInteger line) {
46 | return ^(NSString *description, QCKDSLEmptyBlock closure) {
47 | [[World sharedWorld] itWithDescription:description
48 | flags:flags
49 | file:file
50 | line:line
51 | closure:closure];
52 | };
53 | }
54 |
55 | QCKItBehavesLikeBlock qck_itBehavesLike_builder(NSDictionary *flags, NSString *file, NSUInteger line) {
56 | return ^(NSString *name, QCKDSLSharedExampleContext context) {
57 | [[World sharedWorld] itBehavesLikeSharedExampleNamed:name
58 | sharedExampleContext:context
59 | flags:flags
60 | file:file
61 | line:line];
62 | };
63 | }
64 |
65 | void qck_pending(NSString *description, QCKDSLEmptyBlock closure) {
66 | [[World sharedWorld] pending:description closure:closure];
67 | }
68 |
69 | void qck_xdescribe(NSString *description, QCKDSLEmptyBlock closure) {
70 | [[World sharedWorld] xdescribe:description flags:@{} closure:closure];
71 | }
72 |
73 | void qck_xcontext(NSString *description, QCKDSLEmptyBlock closure) {
74 | qck_xdescribe(description, closure);
75 | }
76 |
77 | void qck_fdescribe(NSString *description, QCKDSLEmptyBlock closure) {
78 | [[World sharedWorld] fdescribe:description flags:@{} closure:closure];
79 | }
80 |
81 | void qck_fcontext(NSString *description, QCKDSLEmptyBlock closure) {
82 | qck_fdescribe(description, closure);
83 | }
84 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/Quick.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | //! Project version number for Quick.
4 | FOUNDATION_EXPORT double QuickVersionNumber;
5 |
6 | //! Project version string for Quick.
7 | FOUNDATION_EXPORT const unsigned char QuickVersionString[];
8 |
9 | #import "QuickSpec.h"
10 | #import "QCKDSL.h"
11 | #import "QuickConfiguration.h"
12 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/QuickSpec.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | /**
4 | QuickSpec is a base class all specs written in Quick inherit from.
5 | They need to inherit from QuickSpec, a subclass of XCTestCase, in
6 | order to be discovered by the XCTest framework.
7 |
8 | XCTest automatically compiles a list of XCTestCase subclasses included
9 | in the test target. It iterates over each class in that list, and creates
10 | a new instance of that class for each test method. It then creates an
11 | "invocation" to execute that test method. The invocation is an instance of
12 | NSInvocation, which represents a single message send in Objective-C.
13 | The invocation is set on the XCTestCase instance, and the test is run.
14 |
15 | Most of the code in QuickSpec is dedicated to hooking into XCTest events.
16 | First, when the spec is first loaded and before it is sent any messages,
17 | the +[NSObject initialize] method is called. QuickSpec overrides this method
18 | to call +[QuickSpec spec]. This builds the example group stacks and
19 | registers them with Quick.World, a global register of examples.
20 |
21 | Then, XCTest queries QuickSpec for a list of test methods. Normally, XCTest
22 | automatically finds all methods whose selectors begin with the string "test".
23 | However, QuickSpec overrides this default behavior by implementing the
24 | +[XCTestCase testInvocations] method. This method iterates over each example
25 | registered in Quick.World, defines a new method for that example, and
26 | returns an invocation to call that method to XCTest. Those invocations are
27 | the tests that are run by XCTest. Their selector names are displayed in
28 | the Xcode test navigation bar.
29 | */
30 | @interface QuickSpec : XCTestCase
31 |
32 | /**
33 | Override this method in your spec to define a set of example groups
34 | and examples.
35 |
36 | @code
37 | override func spec() {
38 | describe("winter") {
39 | it("is coming") {
40 | // ...
41 | }
42 | }
43 | }
44 | @endcode
45 |
46 | See DSL.swift for more information on what syntax is available.
47 | */
48 | - (void)spec;
49 |
50 | /**
51 | Returns the currently executing spec. Use in specs that require XCTestCase
52 | methods, e.g. expectationWithDescription.
53 | */
54 | @property (class, nonatomic, readonly) QuickSpec *current;
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #if __has_include("Quick-Swift.h")
5 | #import "Quick-Swift.h"
6 | #else
7 | #import
8 | #endif
9 |
10 | @interface XCTestSuite (QuickTestSuiteBuilder)
11 | @end
12 |
13 | @implementation XCTestSuite (QuickTestSuiteBuilder)
14 |
15 | /**
16 | In order to ensure we can correctly build dynamic test suites, we need to
17 | replace some of the default test suite constructors.
18 | */
19 | + (void)load {
20 | Method testCaseWithName = class_getClassMethod(self, @selector(testSuiteForTestCaseWithName:));
21 | Method hooked_testCaseWithName = class_getClassMethod(self, @selector(qck_hooked_testSuiteForTestCaseWithName:));
22 | method_exchangeImplementations(testCaseWithName, hooked_testCaseWithName);
23 | }
24 |
25 | /**
26 | The `+testSuiteForTestCaseWithName:` method is called when a specific test case
27 | class is run from the Xcode test navigator. If the built test suite is `nil`,
28 | Xcode will not run any tests for that test case.
29 |
30 | Given if the following test case class is run from the Xcode test navigator:
31 |
32 | FooSpec
33 | testFoo
34 | testBar
35 |
36 | XCTest will invoke this once per test case, with test case names following this format:
37 |
38 | FooSpec/testFoo
39 | FooSpec/testBar
40 | */
41 | + (nullable instancetype)qck_hooked_testSuiteForTestCaseWithName:(nonnull NSString *)name {
42 | return [QuickTestSuite selectedTestSuiteForTestCaseWithName:name];
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickSpecBase/QuickSpecBase.m:
--------------------------------------------------------------------------------
1 | #import "QuickSpecBase.h"
2 |
3 | #pragma mark - _QuickSelectorWrapper
4 |
5 | @interface _QuickSelectorWrapper ()
6 | @property(nonatomic, assign) SEL selector;
7 | @end
8 |
9 | @implementation _QuickSelectorWrapper
10 |
11 | - (instancetype)initWithSelector:(SEL)selector {
12 | self = [super init];
13 | _selector = selector;
14 | return self;
15 | }
16 |
17 | @end
18 |
19 |
20 | #pragma mark - _QuickSpecBase
21 |
22 | @implementation _QuickSpecBase
23 |
24 | - (instancetype)init {
25 | self = [super initWithInvocation: nil];
26 | return self;
27 | }
28 |
29 | /**
30 | Invocations for each test method in the test case. QuickSpec overrides this method to define a
31 | new method for each example defined in +[QuickSpec spec].
32 |
33 | @return An array of invocations that execute the newly defined example methods.
34 | */
35 | + (NSArray *)testInvocations {
36 | NSArray<_QuickSelectorWrapper *> *wrappers = [self _qck_testMethodSelectors];
37 | NSMutableArray *invocations = [NSMutableArray arrayWithCapacity:wrappers.count];
38 |
39 | for (_QuickSelectorWrapper *wrapper in wrappers) {
40 | SEL selector = wrapper.selector;
41 | NSMethodSignature *signature = [self instanceMethodSignatureForSelector:selector];
42 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
43 | invocation.selector = selector;
44 |
45 | [invocations addObject:invocation];
46 | }
47 |
48 | return invocations;
49 | }
50 |
51 | + (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors {
52 | return @[];
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/Pods/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface _QuickSelectorWrapper : NSObject
5 | - (instancetype)initWithSelector:(SEL)selector;
6 | @end
7 |
8 | @interface _QuickSpecBase : XCTestCase
9 | + (NSArray<_QuickSelectorWrapper *> *)_qck_testMethodSelectors;
10 | - (instancetype)init NS_DESIGNATED_INITIALIZER;
11 | @end
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 8.0.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Nimble : NSObject
3 | @end
4 | @implementation PodsDummy_Nimble
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "Nimble.h"
14 | #import "DSL.h"
15 | #import "NMBExceptionCapture.h"
16 | #import "NMBStringify.h"
17 | #import "CwlCatchException.h"
18 | #import "CwlMachBadInstructionHandler.h"
19 | #import "mach_excServer.h"
20 | #import "CwlPreconditionTesting.h"
21 |
22 | FOUNDATION_EXPORT double NimbleVersionNumber;
23 | FOUNDATION_EXPORT const unsigned char NimbleVersionString[];
24 |
25 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble.modulemap:
--------------------------------------------------------------------------------
1 | framework module Nimble {
2 | umbrella header "Nimble-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nimble/Nimble.xcconfig:
--------------------------------------------------------------------------------
1 | APPLICATION_EXTENSION_API_ONLY = YES
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Nimble
3 | ENABLE_BITCODE = NO
4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"
5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
6 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -weak-lswiftXCTest -weak_framework "XCTest"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS $(inherited) -suppress-warnings
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_ROOT = ${SRCROOT}
11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nimble
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_MultiProgressViewTests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_MultiProgressViewTests
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_MultiProgressViewTestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_MultiProgressViewTestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "Quick" -framework "XCTest" -weak_framework "XCTest"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_MultiProgressViewTests {
2 | umbrella header "Pods-MultiProgressViewTests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-MultiProgressViewTests/Pods-MultiProgressViewTests.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks" "${PODS_CONFIGURATION_BUILD_DIR}/Nimble" "${PODS_CONFIGURATION_BUILD_DIR}/Quick"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Nimble/Nimble.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Quick/Quick.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_LDFLAGS = $(inherited) -framework "Nimble" -framework "Quick" -framework "XCTest" -weak_framework "XCTest"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
11 | PODS_ROOT = ${SRCROOT}/Pods
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Quick : NSObject
3 | @end
4 | @implementation PodsDummy_Quick
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "QuickConfiguration.h"
14 | #import "QCKDSL.h"
15 | #import "Quick.h"
16 | #import "QuickSpec.h"
17 |
18 | FOUNDATION_EXPORT double QuickVersionNumber;
19 | FOUNDATION_EXPORT const unsigned char QuickVersionString[];
20 |
21 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick.modulemap:
--------------------------------------------------------------------------------
1 | framework module Quick {
2 | umbrella header "Quick-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Quick/Quick.xcconfig:
--------------------------------------------------------------------------------
1 | APPLICATION_EXTENSION_API_ONLY = YES
2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Quick
3 | ENABLE_BITCODE = NO
4 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"
5 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
6 | OTHER_LDFLAGS = $(inherited) -Xlinker -no_application_extension -framework "XCTest"
7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
8 | PODS_BUILD_DIR = ${BUILD_DIR}
9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_ROOT = ${SRCROOT}
11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Quick
12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
13 | SKIP_INSTALL = YES
14 |
--------------------------------------------------------------------------------
/Sources/MultiProgressView.h:
--------------------------------------------------------------------------------
1 | //
2 | // MultiProgressView.h
3 | // MultiProgressView
4 | //
5 | // Created by Mac Gallagher on 3/26/19.
6 | // Copyright © 2019 Mac Gallagher. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for MultiProgressView.
12 | FOUNDATION_EXPORT double MultiProgressViewVersionNumber;
13 |
14 | //! Project version string for MultiProgressView.
15 | FOUNDATION_EXPORT const unsigned char MultiProgressViewVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Sources/MultiProgressView.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Sources/MultiProgressView/AlignmentType.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | public enum AlignmentType {
26 | case left
27 | case topLeft
28 | case top
29 | case topRight
30 | case right
31 | case bottomRight
32 | case bottom
33 | case bottomLeft
34 | case center
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/MultiProgressView/Internal/TapGestureRecognizer.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | /// A testable `UITapGestureRecognizer`
28 | class TapGestureRecognizer: UITapGestureRecognizer {
29 |
30 | private weak var testTarget: AnyObject?
31 | private var testAction: Selector?
32 |
33 | private var testLocation: CGPoint?
34 |
35 | override init(target: Any?, action: Selector?) {
36 | testTarget = target as AnyObject
37 | testAction = action
38 | super.init(target: target, action: action)
39 | }
40 |
41 | override func location(in view: UIView?) -> CGPoint {
42 | return testLocation ?? super.location(in: view)
43 | }
44 |
45 | func performTap(withLocation location: CGPoint?) {
46 | testLocation = location
47 | if let action = testAction {
48 | testTarget?.performSelector(onMainThread: action,
49 | with: self,
50 | waitUntilDone: true)
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/MultiProgressView/LineCapType.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | public enum LineCapType {
26 | case round
27 | case butt
28 | case square
29 | }
30 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Mocks/MockLayoutProvider.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | @testable import MultiProgressView
26 |
27 | class MockLayoutProvider: LayoutProvidable {
28 |
29 | var testTrackFrame: CGRect = .zero
30 | func trackFrame(_ progressView: MultiProgressView) -> CGRect {
31 | return testTrackFrame
32 | }
33 |
34 | var testTrackImageViewFrame: CGRect = .zero
35 | func trackImageViewFrame(_ progressView: MultiProgressView) -> CGRect {
36 | return testTrackImageViewFrame
37 | }
38 |
39 | var testCornerRadius: CGFloat = 0.0
40 | func cornerRadius(_ progressView: MultiProgressView) -> CGFloat {
41 | return testCornerRadius
42 | }
43 |
44 | var testTrackCornerRadius: CGFloat = 0.0
45 | func trackCornerRadius(_ progressView: MultiProgressView) -> CGFloat {
46 | return testTrackCornerRadius
47 | }
48 |
49 | var testSectionFrame: CGRect = .zero
50 | func sectionFrame(_ progressView: MultiProgressView, section: Int) -> CGRect {
51 | return testSectionFrame
52 | }
53 |
54 | var testSectionImageViewFrame: CGRect = .zero
55 | func sectionImageViewFrame(_ section: ProgressViewSection) -> CGRect {
56 | return testSectionImageViewFrame
57 | }
58 |
59 | var testAnchorConstraints: [NSLayoutConstraint] = []
60 | var anchorToSuperviewAlignment: AlignmentType?
61 | var anchorToSuperviewInsets: UIEdgeInsets?
62 |
63 | func anchorToSuperview(_ view: UIView,
64 | withAlignment alignment: AlignmentType,
65 | insets: UIEdgeInsets) -> [NSLayoutConstraint] {
66 | anchorToSuperviewAlignment = alignment
67 | anchorToSuperviewInsets = insets
68 | return testAnchorConstraints
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Mocks/MockMultiProgressViewDataSource.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import MultiProgressView
26 |
27 | class MockMultiProgressViewDataSource: MultiProgressViewDataSource {
28 |
29 | // swiftlint:disable:next implicitly_unwrapped_optional
30 | private var numberOfSections: Int!
31 |
32 | lazy var progressViewSections: [ProgressViewSection] = {
33 | var sections = [ProgressViewSection]()
34 | for index in 0.. Int {
45 | return numberOfSections
46 | }
47 |
48 | func progressView(_ progressView: MultiProgressView, viewForSection section: Int) -> ProgressViewSection {
49 | return progressViewSections[section]
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Mocks/MockProgressViewDelegate.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import MultiProgressView
26 |
27 | class MockProgressViewDelegate: MultiProgressViewDelegate {
28 |
29 | var didTapSectionAtCalled: Bool = false
30 | var didTapSectionIndex: Int?
31 |
32 | func progressView(_ progressView: MultiProgressView, didTapSectionAt index: Int) {
33 | didTapSectionAtCalled = true
34 | didTapSectionIndex = index
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Mocks/MockProgressViewSectionDelegate.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | @testable import MultiProgressView
26 |
27 | class MockProgressViewSectionDelegate: ProgressViewSectionDelegate {
28 |
29 | var didTapSectionCalled: Bool = false
30 | func didTapSection(_ section: ProgressViewSection) {
31 | didTapSectionCalled = true
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/NSLayoutConstraint+TestHelpers.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | import UIKit
26 |
27 | extension NSLayoutConstraint {
28 |
29 | override open func isEqual(_ object: Any?) -> Bool {
30 | guard let constraint = object as? NSLayoutConstraint else { return false }
31 |
32 | guard let firstItem = firstItem as? UIView,
33 | let constraintFirstItem = constraint.firstItem as? UIView else { return false }
34 |
35 | guard let secondItem = secondItem as? UIView,
36 | let constraintSecondItem = constraint.secondItem as? UIView else { return false }
37 |
38 | guard relation == constraint.relation,
39 | constant == constraint.constant,
40 | constant == constraint.constant,
41 | firstItem == constraintFirstItem,
42 | secondItem == constraintSecondItem,
43 | multiplier == constraint.multiplier,
44 | firstAttribute == constraint.firstAttribute,
45 | secondAttribute == constraint.secondAttribute else { return false }
46 |
47 | return true
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Testables/TestableMultiProgressView.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | @testable import MultiProgressView
26 |
27 | class TestableMultiProgressView: MultiProgressView {
28 |
29 | var setNeedsLayoutCalled: Bool = false
30 | override func setNeedsLayout() {
31 | setNeedsLayoutCalled = true
32 | }
33 |
34 | var layoutIfNeededCalled: Bool = false
35 | override func layoutIfNeeded() {
36 | layoutIfNeededCalled = true
37 | }
38 |
39 | var reloadDataCalled: Bool = false
40 | override func reloadData() {
41 | super.reloadData()
42 | reloadDataCalled = true
43 | }
44 |
45 | var updateCornerRadiusCalled: Bool = false
46 | override func updateCornerRadius() {
47 | super.updateCornerRadius()
48 | updateCornerRadiusCalled = true
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Tests/MultiProgressViewTests/Testables/TestableProgressViewSection.swift:
--------------------------------------------------------------------------------
1 | ///
2 | /// MIT License
3 | ///
4 | /// Copyright (c) 2020 Mac Gallagher
5 | ///
6 | /// Permission is hereby granted, free of charge, to any person obtaining a copy
7 | /// of this software and associated documentation files (the "Software"), to deal
8 | /// in the Software without restriction, including without limitation the rights
9 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | /// copies of the Software, and to permit persons to whom the Software is
11 | /// furnished to do so, subject to the following conditions:
12 | ///
13 | /// The above copyright notice and this permission notice shall be included in all
14 | /// copies or substantial portions of the Software.
15 | ///
16 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | /// SOFTWARE.
23 | ///
24 |
25 | @testable import MultiProgressView
26 |
27 | class TestableProgressViewSection: ProgressViewSection {
28 |
29 | var setNeedsLayoutCalled: Bool = false
30 | override func setNeedsLayout() {
31 | setNeedsLayoutCalled = true
32 | }
33 |
34 | var sendSubviewToBackView: UIView?
35 | override func sendSubviewToBack(_ view: UIView) {
36 | sendSubviewToBackView = view
37 | }
38 | }
39 |
--------------------------------------------------------------------------------