├── .github
├── ISSUE_TEMPLATE
│ ├── bug.md
│ ├── feature.md
│ ├── question.md
│ └── task.md
├── PULL_REQUEST_TEMPLATE.md
├── codecov.yml
├── config.yml
├── semantic.yml
└── workflows
│ ├── build.yml
│ └── build_pr.yml
├── .gitignore
├── .hound.yml
├── .swiftlint.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Configurations
├── Info-iOS-Tests.plist
├── Info-iOS.plist
├── Info-macOS-Tests.plist
├── Info-macOS.plist
├── Project-Debug.xcconfig
├── Project-Release.xcconfig
├── Project-Shared.xcconfig
├── Target-iOS-Debug.xcconfig
├── Target-iOS-Release.xcconfig
├── Target-iOS-Shared.xcconfig
├── Target-iOS-Tests-Debug.xcconfig
├── Target-iOS-Tests-Release.xcconfig
├── Target-iOS-Tests-Shared.xcconfig
├── Target-macOS-Debug.xcconfig
├── Target-macOS-Release.xcconfig
├── Target-macOS-Shared.xcconfig
├── Target-macOS-Tests-Debug.xcconfig
├── Target-macOS-Tests-Release.xcconfig
└── Target-macOS-Tests-Shared.xcconfig
├── Documentation
├── ADRs
│ ├── ADR-001-Language_choice.md
│ ├── ADR-002-Coding_standard.md
│ ├── ADR-003-Organization_of_type_members.md
│ ├── ADR-004-Dependencies-management.md
│ └── ADR-005-Project-Structure.md
├── CORE_CONTRIBUTOR.md
├── VISION.md
└── images
│ ├── 04_destination_dir.png
│ ├── 08_xcode_spm_search.png
│ ├── 09_xcode_spm_options.png
│ ├── 10_xcode_spm_add_package.png
│ ├── 11_xcode_carthage_xcframework.png
│ ├── 12_xcode_scheme_env_setup.png
│ └── pact-swift.png
├── LICENSE.md
├── Package.resolved
├── Package.swift
├── PactSwift.xcfilelist
├── PactSwift.xcodeproj
├── project.pbxproj
└── xcshareddata
│ ├── IDETemplateMacros.plist
│ └── xcschemes
│ ├── PactSwift-iOS.xcscheme
│ └── PactSwift-macOS.xcscheme
├── README.md
├── SECURITY.md
├── Scripts
├── BuildPhases
│ ├── lint-project
│ ├── lint-target
│ ├── validate-build-settings
│ └── validate-project-config
├── build_file_list_and_swiftlint
├── carthage
├── check_build_tools
├── prepare_build_tools
├── release
└── run_tests
├── Sources
├── ExampleGenerators
│ ├── DateTime.swift
│ ├── DateTimeExpression.swift
│ ├── ExampleGenerator.swift
│ ├── ProviderStateGenerator.swift
│ ├── RandomBool.swift
│ ├── RandomDate.swift
│ ├── RandomDateTime.swift
│ ├── RandomDecimal.swift
│ ├── RandomHexadecimal.swift
│ ├── RandomInt.swift
│ ├── RandomString.swift
│ ├── RandomTime.swift
│ └── RandomUUID.swift
├── Extensions
│ ├── Bundle+PactSwift.swift
│ ├── Date+PactSwift.swift
│ ├── Dictionary+PactSwift.swift
│ ├── MockServer+Async.swift
│ ├── Sequence+PactSwift.swift
│ ├── String+PactSwift.swift
│ ├── Task+Timeout.swift
│ └── UUID+PactSwift.swift
├── Headers
│ └── PactSwift.h
├── Matchers
│ ├── DecimalLike.swift
│ ├── EachKeyLike.swift
│ ├── EachLike.swift
│ ├── EqualTo.swift
│ ├── FromProviderState.swift
│ ├── IncludesLike.swift
│ ├── IntegerLike.swift
│ ├── MatchNull.swift
│ ├── Matcher.swift
│ ├── OneOf.swift
│ ├── RegexLike.swift
│ └── SomethingLike.swift
├── MockService+Concurrency.swift
├── MockService+Extension.swift
├── MockService.swift
├── Model
│ ├── AnyEncodable.swift
│ ├── Constants.swift
│ ├── EncodingError.swift
│ ├── ErrorReportable.swift
│ ├── ErrorReporter.swift
│ ├── ExampleGeneratorExpressible.swift
│ ├── Interaction.swift
│ ├── MatchingRuleExpressible.swift
│ ├── Metadata.swift
│ ├── Pact.swift
│ ├── PactBroker.swift
│ ├── PactHTTPMethod.swift
│ ├── PactInteractionElement.swift
│ ├── PactInteractionNode.swift
│ ├── PactPathParameter.swift
│ ├── PactSwiftVersion.swift
│ ├── Pacticipant.swift
│ ├── ProviderState.swift
│ ├── ProviderVerifier+Error.swift
│ ├── ProviderVerifier+Options.swift
│ ├── ProviderVerifier+Provider.swift
│ ├── Request.swift
│ ├── Response.swift
│ ├── Toolbox.swift
│ ├── TransferProtocol.swift
│ ├── VersionSelector.swift
│ └── WIPPacts.swift
├── PFMockService.swift
├── PactBuilder.swift
├── ProviderVerifier.swift
└── Toolbox
│ ├── Logger.swift
│ └── PactFileManager.swift
├── Tests
├── ExampleGenerators
│ ├── DateTimeExpressionTests.swift
│ ├── DateTimeTests.swift
│ ├── ObjCExampleGeneratorTests.swift
│ ├── ProviderStateGeneratorTests.swift
│ ├── RandomBooleanTests.swift
│ ├── RandomDateTests.swift
│ ├── RandomDateTimeTests.swift
│ ├── RandomDecimalTests.swift
│ ├── RandomHexadecimalTests.swift
│ ├── RandomIntTests.swift
│ ├── RandomStringTests.swift
│ ├── RandomTimeTests.swift
│ └── RandomUuidTests.swift
├── Extensions
│ └── String+PactSwiftTests.swift
├── Matchers
│ ├── DecimalLikeTests.swift
│ ├── EachKeyLikeTests.swift
│ ├── EachLikeTests.swift
│ ├── EqualToTests.swift
│ ├── FromProviderStateTests.swift
│ ├── IncludesLikeTests.swift
│ ├── IntegerLikeTests.swift
│ ├── MatchNullTests.swift
│ ├── ObjCMatcherTests.swift
│ ├── OneOfTests.swift
│ ├── RegexLikeTests.swift
│ └── SomethingLikeTests.swift
├── Model
│ ├── AnyEncodableTests.swift
│ ├── InteractionTests.swift
│ ├── MetadataTests.swift
│ ├── PactBrokerTests.swift
│ ├── PactBuilderTests.swift
│ ├── PactHTTPMethodTests.swift
│ ├── PactTests.swift
│ ├── PacticipantTests.swift
│ ├── ProviderVerifier+OptionsTests.swift
│ ├── ToolboxTests.swift
│ ├── TransferProtocolTests.swift
│ ├── VersionSelectorTests.swift
│ └── WIPPactsTests.swift
├── Services
│ ├── AsyncMockServiceTests.swift
│ ├── MockServiceTests.swift
│ ├── MockServiceWithDirectoryPathTests.swift
│ ├── PFMockServiceTests.swift
│ ├── PactContractTests.swift
│ └── ProviderVerifierTests.swift
└── TestHelpers
│ ├── DateHelper.swift
│ ├── ErrorCapture.swift
│ ├── ExampleGeneratorTestHelpers.swift
│ └── MatcherTestHelpers.swift
└── codecov.yml
/.github/ISSUE_TEMPLATE/bug.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report to help us improve.
4 | title: 'Bug: ...'
5 | labels: "bug"
6 | assignees: ''
7 | ---
8 | # 🌎 Environment
9 |
10 | - Xcode: [e.g. 11.4]
11 | - Platform: [e.g. iOS]
12 | - Version/Release: [e.g. 1.0.2]
13 | - Dependency manager: [e.g. Carthage 0.38]
14 |
15 | # 💬 Description
16 |
17 |
18 |
19 | # 🦶 Reproduction Steps
20 |
21 |
22 |
23 | Steps to reproduce the behavior:
24 | 1. Do this...
25 | 2. Run this `xcrun ...`
26 | 3. Etc.
27 |
28 | # 🤔 Expected Results
29 |
30 |
31 |
32 | # 😲 Actual Results
33 |
34 |
35 |
36 | ## 🌳 Logs
37 |
38 | ```
39 | Include any logs or command output if applicable...
40 | ```
41 |
42 | ## 📄 Stack Traces
43 |
44 | ```
45 | Include a stack trace if applicable...
46 | ```
47 |
48 | # 🤝 Relationships
49 |
50 | - Related PRs or Issues: #xxx, #yyy
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | about: Create a feature request to enhance the project.
4 | title: ''
5 | labels: 'enhancement'
6 | assignees: ''
7 |
8 | ---
9 |
10 | # 🗣 Context
11 |
12 |
13 |
14 | # 💬 Narrative
15 |
16 | When ...
17 | I want ...
18 | So that ...
19 |
20 | # 📝 Notes
21 |
22 |
23 |
24 | # 🏗 Design
25 |
26 |
27 |
28 | # ✅ Acceptance Criteria
29 |
30 | **GIVEN** ...
31 | **WHEN** ...
32 | **THEN** ...
33 |
34 | # 🚫 Out of Scope
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Just looking for some information about a thing
4 | title: 'Question: ...'
5 | labels: "question"
6 | assignees: ''
7 | ---
8 | # ❔ Question
9 |
10 |
11 |
12 | # 💬 Context
13 |
14 |
15 |
16 |
17 | # 🤝 Relationships
18 |
19 | - Other Related Issues: #xxx, #yyy
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/task.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Task
3 | about: Create a technical task that needs doing.
4 | title: 'Task: ...'
5 | labels: "task"
6 | assignees: ''
7 | ---
8 | # ❕ Problem Statement
9 |
10 |
11 |
12 | # 💬 Task Description
13 |
14 |
15 |
16 | # 👩🔧 Technical Design Notes
17 |
18 |
19 |
20 | # 🤝 Relationships
21 |
22 | - Other Related Issues: #xxx, #yyy
23 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | - ☝️ Provide a short but descriptive title for this PR.
2 | - 🏷 Remember to label your pull request appropriately and select appropriate code reviewers.
3 |
4 | _Provide a more descriptive summary of the changes in this PR here._
5 |
6 | # 📝 Summary of Changes
7 |
8 | Changes proposed in this pull request:
9 |
10 | - Resolves issue #99999 by doing the thing with another thing
11 | - Add more details here...
12 | - ...
13 |
14 | # ⚠️ Items of Note
15 |
16 | _Document anything here that you think the reviewer(s) of this PR may need to know, or would be of specific interest._
17 |
18 | # 🧐🗒 Reviewer Notes
19 |
20 | ## 💁 Example
21 |
22 | _Add an example of using the changes you've implemented (eg, a screenshot or text dump of the output)._
23 |
24 | ## 🔨 How To Test
25 |
26 | _Provide instructions on how to test your changes._
--------------------------------------------------------------------------------
/.github/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | require_ci_to_pass: yes
4 |
5 | coverage:
6 | precision: 2
7 | round: down
8 | range: "70...90"
9 |
10 | status:
11 | project: yes
12 | patch: yes
13 | changes: no
14 |
15 | ignore:
16 | - "Tests/**"
17 |
18 | parsers:
19 | gcov:
20 | branch_detection:
21 | conditional: yes
22 | loop: yes
23 | method: no
24 | macro: no
25 |
26 | comment:
27 | layout: "header, diff"
28 | behavior: default
29 | require_changes: no
30 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | updateDocsWhiteList:
2 | - BUG
3 | - Chore
4 | - minor
5 |
6 | updateDocsComment: >
7 | Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would update some of our documentation based on your changes.
8 | requestInfoReplyComment: >
9 | We would appreciate it if you could provide us with more info about this issue/pr!
10 | requestInfoLabelToAdd: request-more-info
11 |
12 | newPRWelcomeComment: >
13 | :tada: Thanks so much for opening your first PR in this project! We really do appreciate your help! :heart:
14 | firstPRMergeComment: >
15 | Congrats on merging your first pull request in this project! :tada: You're awesome! :metal:
16 | newIssueWelcomeComment: >
17 | Thanks for opening this issue, a maintainer will get back to you shortly! cc/ @surpher
18 | sentimentBotToxicityThreshold: .7
19 |
20 | sentimentBotReplyComment: >
21 | Please be sure to review the code of conduct and be respectful of other users. cc/ @surpher
22 | lockThreads:
23 | toxicityThreshold: .7
24 | numComments: 2
25 | setTimeInHours: 72
26 | replyComment: >
27 | This thread is being locked due to exceeding the toxicity minimums. cc/ @surpher
28 |
--------------------------------------------------------------------------------
/.github/semantic.yml:
--------------------------------------------------------------------------------
1 | # Always validate the PR title and commits (this is important because release notes are automated and we rely on semantic commit titles)
2 | titleAndCommits: true
3 |
4 | # By default types specified in commitizen/conventional-commit-types is used.
5 | # See: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json
6 | # You can override the valid types
7 | types:
8 | - feat
9 | - feature
10 | - fix
11 | - docs
12 | - style
13 | - refactor
14 | - perf
15 | - test
16 | - build
17 | - ci
18 | - chore
19 | - revert
20 | - tech
21 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | pull_request:
5 | types:
6 | - opened
7 | - synchronize
8 | - reopened
9 | - ready_for_review
10 | workflow_dispatch:
11 |
12 | env:
13 | RUST_TARGET_PATH: pact-reference
14 |
15 | jobs:
16 | test_ios:
17 | name: "🤖 Test iOS"
18 | runs-on: ${{ matrix.host }}
19 |
20 | strategy:
21 | fail-fast: true
22 | matrix:
23 | host: [macos-13, macos-14]
24 | platform: [ios, macos]
25 | include:
26 | - platform: ios
27 | scheme: "PactSwift-iOS"
28 | destination: "platform=iOS Simulator,name=iPhone 15 Pro"
29 | - platform: macos
30 | scheme: "PactSwift-macOS"
31 | destination: "arch=x86_64"
32 | - host: macos-13
33 | xcode: 14.3.1
34 | - host: macos-14
35 | xcode: 15.3
36 |
37 | env:
38 | SCHEME: "PactSwift-iOS"
39 | DESTINATION: ${{ matrix.destination }}
40 |
41 | concurrency:
42 | group: test_${{ matrix.host }}_${{ matrix.xcode }}_iOS_${{ github.ref }}
43 | cancel-in-progress: true
44 |
45 | steps:
46 | - name: "🧑💻 Checkout repository"
47 | uses: actions/checkout@v3
48 |
49 | - name: "🏭 Use Xcode ${{ matrix.xcode }}"
50 | run: sudo xcode-select -switch /Applications/Xcode_${{ matrix.xcode }}.app
51 |
52 | - name: "🧪 Run tests (xcodebuild)"
53 | run: |
54 | set -o pipefail && \
55 | xcodebuild -resolvePackageDependencies && \
56 | xcodebuild test \
57 | -project PactSwift.xcodeproj \
58 | -scheme "$SCHEME"\
59 | -destination "$DESTINATION" \
60 | | xcbeautify
61 |
62 | # - name: "⚗️ Run tests (swift)"
63 | # run: |
64 | # swift build
65 | # swift test -c release
66 |
--------------------------------------------------------------------------------
/.github/workflows/build_pr.yml:
--------------------------------------------------------------------------------
1 | name: Build Pull Request
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - '!main'
7 |
8 | jobs:
9 | test_macos:
10 | name: "🤖 Test macOS"
11 | runs-on: macos-13
12 |
13 | env:
14 | XCODE_VERSION: 14.3.1
15 |
16 | concurrency:
17 | group: test_macos13_darwin_$SCHEME_${{ github.ref }}
18 | cancel-in-progress: true
19 |
20 | steps:
21 | - name: "🧑💻 Checkout repository"
22 | uses: actions/checkout@v3
23 |
24 | - name: "⚙️ Use Xcode ${{ env.XCODE_VERSION }}"
25 | run: sudo xcode-select -switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app
26 |
27 | - name: "🧰 Prepare tools"
28 | run: |
29 | Scripts/prepare_build_tools
30 |
31 | - name: "🧪 xcodebuild clean test"
32 | run: |
33 | set -o pipefail && xcodebuild -resolvePackageDependencies | xcbeautify && xcodebuild clean test -project PactSwift.xcodeproj -scheme "PactSwift-macOS" -destination "arch=x86_64" | xcbeautify
34 |
35 | - name: "⚗️ swift test"
36 | run: |
37 | set -o pipefail && swift test -c release
38 |
39 | test_ios:
40 | name: "🤖 Test iOS"
41 | runs-on: macos-13
42 | needs: [test_macos]
43 |
44 | env:
45 | SCHEME: "PactSwift-iOS"
46 | DESTINATION: "platform=iOS Simulator,name=iPhone 14 Pro"
47 | XCODE_VERSION: 14.3.1
48 |
49 | concurrency:
50 | group: test_macos13_ios_$SCHEME_${{ github.ref }}
51 | cancel-in-progress: true
52 |
53 | steps:
54 | - name: "🧑💻 Checkout repository"
55 | uses: actions/checkout@v3
56 |
57 | - name: "⚙️ Use Xcode ${{ env.XCODE_VERSION }}"
58 | run: sudo xcode-select -switch /Applications/Xcode_${{ env.XCODE_VERSION }}.app
59 |
60 | - name: "🧰 Prepare tools"
61 | run: |
62 | Scripts/prepare_build_tools
63 |
64 | - name: "♘ Test for Carthage"
65 | run: |
66 | set -o pipefail && carthage build --no-skip-current --use-xcframeworks
67 |
68 | - name: "🧪 xcodebuild clean test"
69 | run: |
70 | set -o pipefail && xcodebuild -resolvePackageDependencies | xcbeautify && xcodebuild clean test -project PactSwift.xcodeproj -scheme "PactSwift-iOS" -destination "platform=iOS Simulator,name=iPhone 14 Pro" | xcbeautify
71 |
72 | - name: "⚗️ swift test"
73 | run: |
74 | swift test -c release
75 |
76 | after_success:
77 | needs: [test_ios]
78 | name: "🚚 Build demo projects"
79 | if: github.ref == 'refs/heads/main'
80 | runs-on: ubuntu-latest
81 |
82 | steps:
83 | - name: "🚚 Build demo projects"
84 | run: |
85 | curl -X POST https://api.github.com/repos/surpher/pact-swift-examples/dispatches -H 'Accept: application/vnd.github.everest-preview+json' -u ${{ secrets.PACT_SWIFT_TOKEN }} --data '{"event_type":"PactSwift - ${{ github.event.head_commit.message }}"}'
86 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### macOS ###
2 | # General
3 | .DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | # Icon must end with two \r
8 | Icon
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear in the root of a volume
14 | .DocumentRevisions-V100
15 | .fseventsd
16 | .Spotlight-V100
17 | .TemporaryItems
18 | .Trashes
19 | .VolumeIcon.icns
20 | .com.apple.timemachine.donotpresent
21 |
22 | # Directories potentially created on remote AFP share
23 | .AppleDB
24 | .AppleDesktop
25 | Network Trash Folder
26 | Temporary Items
27 | .apdisk
28 |
29 | ### Xcode ###
30 | # Xcode
31 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
32 |
33 | ## User settings
34 |
35 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
36 |
37 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
38 |
39 | ## Xcode Patch
40 | *.xcodeproj/*
41 | !*.xcodeproj/project.pbxproj
42 | !*.xcodeproj/xcshareddata/
43 | !*.xcworkspace/contents.xcworkspacedata
44 | /*.gcno
45 |
46 | ### Xcode Patch ###
47 | **/xcshareddata/WorkspaceSettings.xcsettings
48 |
49 | ### Swift ###
50 | # Xcode
51 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
52 |
53 | ## Build generated
54 | build/
55 | DerivedData/
56 | tmp/
57 |
58 | ## Various settings
59 | *.pbxuser
60 | !default.pbxuser
61 | *.mode1v3
62 | !default.mode1v3
63 | *.mode2v3
64 | !default.mode2v3
65 | *.perspectivev3
66 | !default.perspectivev3
67 | xcuserdata/
68 |
69 | ## Other
70 | *.moved-aside
71 | *.xccheckout
72 | *.xcscmblueprint
73 |
74 | ## Obj-C/Swift specific
75 | *.hmap
76 | *.ipa
77 | *.dSYM.zip
78 | *.dSYM
79 |
80 | ## Playgrounds
81 | timeline.xctimeline
82 | playground.xcworkspace
83 |
84 | ######################
85 | ## Package managers ##
86 | ######################
87 |
88 | ### SwiftPackageManager ###
89 |
90 | Packages/
91 | .build/
92 |
93 | # Add this line if you want to avoid checking in Xcode SPM integration.
94 | # .swiftpm/xcode
95 |
96 | ### Carthage ###
97 | # Carthage
98 | #
99 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
100 | # Carthage/Checkouts
101 |
102 | Carthage/
103 | .swiftpm*
104 |
105 | ###################
106 | ## Binaries ##
107 | ###################
108 | *.a
109 |
--------------------------------------------------------------------------------
/.hound.yml:
--------------------------------------------------------------------------------
1 | swiftlint:
2 | config_file: .swiftlint.yml
3 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - force_cast
3 | - identifier_name
4 | - large_tuple
5 | - operator_whitespace
6 | - unused_declaration
7 | - unused_import
8 |
9 | opt_in_rules:
10 | - closure_body_length
11 | - closure_end_indentation
12 | - closure_parameter_position
13 | - closure_spacing
14 | - collection_alignment
15 | - contains_over_filter_count
16 | - contains_over_filter_is_empty
17 | - contains_over_first_not_nil
18 | - contains_over_range_nil_comparison
19 | - convenience_type
20 | - discouraged_object_literal
21 | - empty_collection_literal
22 | - empty_count
23 | - empty_string
24 | - empty_xctest_method
25 | - explicit_init
26 | - first_where
27 | - flatmap_over_map_reduce
28 | - identical_operands
29 | - implicit_return
30 | - joined_default_parameter
31 | - last_where
32 | - legacy_multiple
33 | - legacy_random
34 | - literal_expression_end_indentation
35 | - lower_acl_than_parent
36 | - modifier_order
37 | - number_separator
38 | - operator_usage_whitespace
39 | - overridden_super_call
40 | - override_in_extension
41 | - private_action
42 | - prohibited_super_call
43 | - reduce_into
44 | - redundant_nil_coalescing
45 | - redundant_type_annotation
46 | - sorted_first_last
47 | - sorted_imports
48 | - static_operator
49 | - toggle_bool
50 | - trailing_whitespace
51 | - unneeded_parentheses_in_closure_argument
52 | - yoda_condition
53 | - xct_specific_matcher
54 |
55 | analyzer_rules:
56 | - unused_declaration
57 | - unused_import
58 |
59 | line_length:
60 | warning: 180
61 | ignores_function_declarations: true
62 | ignores_comments: false
63 |
64 | modifier_order:
65 | preferred_modifier_order: [acl, override]
66 |
67 | nesting:
68 | type_level: 2
69 |
70 | included:
71 | - Sources
72 |
73 | excluded:
74 | - Carthage
75 | - Tests
76 |
77 | trailing_comma:
78 | mandatory_comma: true
79 |
--------------------------------------------------------------------------------
/Configurations/Info-iOS-Tests.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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Configurations/Info-iOS.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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2020-2021 Marko Justinek. All rights reserved.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Configurations/Info-macOS-Tests.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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Configurations/Info-macOS.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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2020-2021 Marko Justinek. All rights reserved.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Configurations/Project-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Project-Shared.xcconfig"
2 |
3 | ONLY_ACTIVE_ARCH = YES
4 | DEBUG_INFORMATION_FORMAT = dwarf
5 | ENABLE_TESTABILITY = YES
6 |
7 | GCC_DYNAMIC_NO_PIC = NO
8 | GCC_OPTIMIZATION_LEVEL = 0
9 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited)
10 |
11 | SWIFT_OPTIMIZATION_LEVEL = -Onone
12 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
13 |
14 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE
15 |
--------------------------------------------------------------------------------
/Configurations/Project-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Project-Shared.xcconfig"
2 |
3 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
4 | VALIDATE_PRODUCT = YES
5 |
6 | ENABLE_NS_ASSERTIONS = NO
7 |
8 | MTL_ENABLE_DEBUG_INFO = NO
9 |
10 | SWIFT_OPTIMIZATION_LEVEL = -O
11 | SWIFT_COMPILATION_MODE = wholemodule
12 |
--------------------------------------------------------------------------------
/Configurations/Project-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | // !!! WARNING: NEXT LINE IS AUTOMATED - DO NOT CHANGE OR MOVE !!!
2 | MARKETING_VERSION = 1.1.0
3 |
4 | CURRENT_PROJECT_VERSION = 1
5 | VERSIONING_SYSTEM = apple-generic
6 |
7 | SWIFT_VERSION = 5.0
8 |
9 | COPY_PHASE_STRIP = NO
10 |
11 | ALWAYS_SEARCH_USER_PATHS = NO
12 | ENABLE_STRICT_OBJC_MSGSEND = YES
13 |
14 | BUILD_LIBRARY_FOR_DISTRIBUTION = YES
15 |
16 | // GCC
17 |
18 | GCC_NO_COMMON_BLOCKS = YES
19 | GCC_C_LANGUAGE_STANDARD = gnu11
20 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES
21 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR
22 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
23 | GCC_WARN_UNUSED_FUNCTION = YES
24 | GCC_WARN_UNUSED_VARIABLE = YES
25 | GCC_WARN_UNDECLARED_SELECTOR = YES
26 |
27 | MTL_FAST_MATH = YES
28 |
29 | CLANG_CXX_LANGUAGE_STANDARD = gnu++14
30 | CLANG_CXX_LIBRARY = libc++
31 | CLANG_ENABLE_MODULES = YES
32 | CLANG_ENABLE_OBJC_ARC = YES
33 | CLANG_ENABLE_OBJC_WEAK = YES
34 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES
35 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES
36 | CLANG_WARN_EMPTY_BODY = YES
37 | CLANG_WARN_BOOL_CONVERSION = YES
38 | CLANG_WARN_CONSTANT_CONVERSION = YES
39 | CLANG_WARN_ENUM_CONVERSION = YES
40 | CLANG_WARN_INT_CONVERSION = YES
41 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES
42 | CLANG_WARN_INFINITE_RECURSION = YES
43 | CLANG_WARN_STRICT_PROTOTYPES = YES
44 | CLANG_WARN_COMMA = YES
45 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
46 | CLANG_WARN_UNREACHABLE_CODE = YES
47 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES
48 | CLANG_WARN_SUSPICIOUS_MOVE = YES
49 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR
50 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
51 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES
52 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES
53 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR
54 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
55 | CLANG_ANALYZER_NONNULL = YES
56 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE
57 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES
58 |
59 | // Xcode 14
60 |
61 | DEAD_CODE_STRIPPING = YES
62 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-iOS-Shared.xcconfig"
2 |
3 | SWIFT_OPTIMIZATION_LEVEL = -Onone
4 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-iOS-Shared.xcconfig"
2 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | PRODUCT_NAME = PactSwift
2 |
3 | IPHONEOS_DEPLOYMENT_TARGET = 12.0
4 | SDKROOT = iphoneos
5 | INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
6 | SKIP_INSTALL = YES
7 | TARGETED_DEVICE_FAMILY = 1,2
8 | SUPPORTS_MACCATALYST = NO
9 | BUNDLE_VERSION_STRING_SHORT = $(MARKETING_VERSION)
10 |
11 | DYLIB_COMPATIBILITY_VERSION = 1
12 | DYLIB_CURRENT_VERSION = 1
13 | DYLIB_INSTALL_NAME_BASE = @rpath
14 |
15 | INFOPLIST_FILE = Configurations/Info-iOS.plist
16 | PRODUCT_BUNDLE_IDENTIFIER = au.com.pact-foundation.iOS.PactSwift
17 | LIBRARY_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/usr/lib
18 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
19 | FRAMEWORK_SEARCH_PATHS = $(inherited)
20 | HEADER_SEARCH_PATHS = $(PROJECT_DIR)/Sources/Headers
21 |
22 | OTHER_LDFLAGS = -weak_framework XCTEST -weak-lXCTestSwiftSupport
23 |
24 | DEFINES_MODULE = YES
25 | CODE_SIGN_STYLE = Automatic
26 | CLANG_ENABLE_MODULES = YES
27 | ENABLE_BITCODE = NO
28 | ENABLE_TESTING_SEARCH_PATHS = YES
29 |
30 | CODE_SIGN_IDENTITY =
31 | ENABLE_MODULE_VERIFIER = YES
32 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = gnu11 gnu++14
33 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = objective-c objective-c++
34 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Tests-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-iOS-Tests-Shared.xcconfig"
2 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Tests-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-iOS-Tests-Shared.xcconfig"
2 |
--------------------------------------------------------------------------------
/Configurations/Target-iOS-Tests-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | SDKROOT = iphoneos
2 | PRODUCT_NAME = $(TARGET_NAME)
3 | TARGETED_DEVICE_FAMILY = 1,2
4 | IPHONEOS_DEPLOYMENT_TARGET = 12.0
5 |
6 | INFOPLIST_FILE = Configurations/Info-iOS-Tests.plist
7 | PRODUCT_BUNDLE_IDENTIFIER = au.com.pact-foundation.PactSwiftTests
8 | CODE_SIGN_IDENTITY[sdk=macosx*] = -
9 |
10 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
11 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-macOS-Shared.xcconfig"
2 | ONLY_ACTIVE_ARCH = YES
3 |
4 | DEBUG_INFORMATION_FORMAT = dwarf
5 | ENABLE_TESTABILITY = YES
6 |
7 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE
8 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-macOS-Shared.xcconfig"
2 |
3 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
4 | ENABLE_NS_ASSERTIONS = NO
5 |
6 | SWIFT_COMPILATION_MODE = wholemodule
7 | SWIFT_OPTIMIZATION_LEVEL = -O
8 | MTL_ENABLE_DEBUG_INFO = NO
9 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | PRODUCT_NAME = PactSwift
2 |
3 | ONLY_ACTIVE_ARCH = NO
4 |
5 | SDKROOT = macosx
6 | MACOSX_DEPLOYMENT_TARGET = 10.15
7 | CODE_SIGN_STYLE = Automatic
8 |
9 | DEFINES_MODULE = YES
10 | COMBINE_HIDPI_IMAGES = YES
11 | INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
12 | SKIP_INSTALL = YES
13 |
14 | INFOPLIST_FILE = Configurations/Info-macOS.plist
15 | PRODUCT_BUNDLE_IDENTIFIER = au.com.pact-foundation.macOS.PactSwift
16 | DYLIB_INSTALL_NAME_BASE = @rpath
17 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
18 | LIBRARY_SEARCH_PATHS = $(inherited) $(PLATFORM_DIR)/Developer/usr/lib
19 | FRAMEWORK_SEARCH_PATHS = $(inherited)
20 |
21 | OTHER_LDFLAGS = -weak_framework XCTEST -weak-lXCTestSwiftSupport
22 |
23 | DYLIB_COMPATIBILITY_VERSION = 1
24 | DYLIB_CURRENT_VERSION = 1
25 | ALWAYS_SEARCH_USER_PATHS = NO
26 | VERSION_INFO_PREFIX =
27 | COPY_PHASE_STRIP = NO
28 |
29 | GCC_DYNAMIC_NO_PIC = NO
30 | GCC_OPTIMIZATION_LEVEL = 0
31 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited)
32 |
33 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
34 | SWIFT_OPTIMIZATION_LEVEL = -Onone
35 |
36 | ENABLE_TESTING_SEARCH_PATHS = YES
37 |
38 | DEAD_CODE_STRIPPING = YES
39 |
40 | ENABLE_MODULE_VERIFIER = YES
41 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = gnu11 gnu++14
42 | MODULE_VERIFIER_SUPPORTED_LANGUAGES = objective-c objective-c++
43 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Tests-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-macOS-Tests-Shared.xcconfig"
2 |
3 | ONLY_ACTIVE_ARCH = YES
4 | ENABLE_TESTABILITY = YES
5 | GCC_OPTIMIZATION_LEVEL = 0
6 | GCC_DYNAMIC_NO_PIC = NO
7 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited)
8 | SWIFT_OPTIMIZATION_LEVEL = -Onone
9 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
10 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE
11 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
12 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Tests-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Configurations/Target-macOS-Tests-Shared.xcconfig"
2 | SWIFT_OPTIMIZATION_LEVEL = -O
3 | ENABLE_NS_ASSERTIONS = NO
4 | MTL_ENABLE_DEBUG_INFO = NO
5 | SWIFT_COMPILATION_MODE = wholemodule
6 |
--------------------------------------------------------------------------------
/Configurations/Target-macOS-Tests-Shared.xcconfig:
--------------------------------------------------------------------------------
1 | //:configuration = Debug
2 | SDKROOT = macosx
3 | MACOSX_DEPLOYMENT_TARGET = 11.0
4 |
5 | CODE_SIGN_STYLE = Automatic
6 | COMBINE_HIDPI_IMAGES = YES
7 |
8 | INFOPLIST_FILE = Configurations/Info-macOS-Tests.plist
9 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
10 |
11 | PRODUCT_BUNDLE_IDENTIFIER = au.com.pact-foundation.macOS.PactSwift-Tests
12 | PRODUCT_NAME = $(TARGET_NAME)
13 |
14 | MTL_FAST_MATH = YES
15 |
16 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
17 |
18 | DEAD_CODE_STRIPPING = YES
19 |
--------------------------------------------------------------------------------
/Documentation/ADRs/ADR-001-Language_choice.md:
--------------------------------------------------------------------------------
1 | # Context
2 |
3 | iOS applications can be written in Objective-C or Swift. Objective-C offers greater interaction with C++ code but is considered a legacy language choice in the iOS developer community. The `pact-consumer-swift` framework was built to support Objective-C as well, but it's proven to become a bigger challenge supporting both with newer Xcode and Swift versions.
4 |
5 | # Decision
6 |
7 | The framework is written in Swift.
8 |
9 | # Consequences
10 |
--------------------------------------------------------------------------------
/Documentation/ADRs/ADR-003-Organization_of_type_members.md:
--------------------------------------------------------------------------------
1 | # Context
2 |
3 | For legibility and discoverability, it is helpful to have a clear ordering of members within each type. Criteria which factor into this include:
4 |
5 | 1. Member kind (property, method, subtype)
6 | 2. Access (public/internal/private)
7 | 3. Nature of member (stored or computed property, override or unique method)
8 |
9 | There are different approaches to how these should be prioritized in C++/Objective-C, whether you're focussing on the needs of the type's consumer or implementer and which slices of behavior you most want to separate.
10 |
11 | # Decision
12 |
13 | Where possible, members should be organized as follows:
14 |
15 | ```
16 | class MyClass: BaseClass {
17 |
18 | // MARK: - Constants
19 |
20 | public static let valueA = 1
21 | private static let valueB = 2
22 |
23 | // MARK: - Types
24 |
25 | public struct SubTypeA {}
26 | private struct SubTypeB {}
27 |
28 | // MARK: - Stored Properties
29 |
30 | public var propertyA = 1
31 | private var propertyB = 2
32 |
33 | // MARK: - Computed Properties
34 |
35 | public var propertyC: Int { return propertyA * 3 }
36 | private var propertyD: Int { return propertyB * 4 }
37 |
38 | // MARK: - Constructors
39 |
40 | public init() {}
41 | private init(param: Int) {}
42 |
43 | // MARK: - Methods
44 |
45 | public static func k() {}
46 |
47 | public func f() {}
48 | private func g() {}
49 |
50 | private static func h() {}
51 |
52 | // MARK: - BaseClass overrides
53 |
54 | public override var propertyL: Int { return propertyA * 3 }
55 | public override func base() {}
56 |
57 | }
58 |
59 | extension MyClass: SomeComformance {
60 |
61 | public var i: Int { return 0 }
62 |
63 | public func j() {}
64 |
65 | }
66 | ```
67 |
68 | Important points to note:
69 |
70 | 1. public before private
71 | 2. static lifetimes before properties before methods
72 | 3. stored properties before computed properties
73 | 4. constructors before other methods
74 | 5. overrides grouped based on the class they override
75 | 6. protocol conformances in separate extensions (unless auto-synthesis is involved)
76 |
77 | In most cases, these sections will not all be present... don't use a heading for a section not included
78 |
79 | # Consequences
80 |
81 | There are a couple points that aren't totally decided.
82 |
83 | They do not *need* to have "mark" headings and when they do, provided the contents themselves are organized, a simple "Properties" or "Methods" is sufficient to cover all methods or properties (e.g. doesn't need to be broken into "Stored" and "Computed").
84 |
85 | However, overrides sections should have a heading indicating which class' methods they override, otherwise its purpose is difficult to understand.
86 |
87 | Static methods are all in one section with the other methods, with public static first and private static last (after all non-static methods). However:
88 |
89 | 1. Most public static functions are constructors and should go in the constructor section (probably ahead of init functions)
90 | 2. Many private static functions are called from just one location, lifted out for purely syntactic reasons. Sometimes these might appear alongside the function they're lifted out-of, sometimes they might appear at the end of the file since they're mostly an implementation detail that can be ignored.
91 |
92 | There's a little flexibility here and when reviewing PR's suggestions and requests for improvement may be made prior to approving a PR.
93 |
--------------------------------------------------------------------------------
/Documentation/ADRs/ADR-004-Dependencies-management.md:
--------------------------------------------------------------------------------
1 | # Context
2 |
3 | Almost all software we write depends on some other code, library or development tool which allows us to build what we want faster. Although this project attempts to avoid bringing in 3rd party dependencies, there are is functionality already written that is critical to this projects success.
4 |
5 | # Decision
6 |
7 | The main dependency is the programmable in-process mock server that can receive network requests and respond with the response we define. This dependency is written in rust and is available at [pact-foundation/pact-reference/rust](https://github.com/pact-foundation/pact-reference/tree/main/rust/pact_mock_server_ffi).
8 |
9 | The binary framework(s) that are built using `cargo lipo --release` command are added into the Xcode project.
10 |
11 | Unfortunately SPM doesn't handle the binary dependencies well at the time of this writing. Therefore a SPM package is required
12 |
13 | There will be a separation of responsibilities between PactSwift framework and PactSwiftServices in a separate (yet embedded) project which will provide extra functionality by reaching out to and/or interact with different services (interacting with Pact Mock Server, etc.).
14 |
15 | Matt's [CwlPreconditionTesting](https://github.com/mattgallagher/CwlPreconditionTesting) is a dependency this project can't really exist without. To support distributon of PactSwift using both Carthage and SPM, the dependency CwlPreconditionTesting is brougt into the PactSwiftServices project (files `./Carthage/Checkouts/CwlPreconditionTesting/*` added into the project itself). For SPM it is defined as a dependency in `./PactSwiftServices/Package.swift`.
16 |
17 | # Consequences
18 |
19 | Due to SPM not handling binary dependencies well. When linking and embedding a binary framework while building and running in Xcode everything works fine, `xcodebuild` command in command line builds the project and dependencies just fine.
20 |
21 | Yet, when running `swift build` in terminal, SPM doesn't know where to find it. That's why a separate SPM package to provide the binary framework as a dependency is required and unfortunately the binary framework is duplicated in the codebase - once in `PactSwiftServices` project and once in `PactMockServer` swift package.
22 |
23 | # Follow-up (September 30, 2020)
24 |
25 | All 3rd party dependencies have been successfully removed from this project/framework.
26 |
--------------------------------------------------------------------------------
/Documentation/CORE_CONTRIBUTOR.md:
--------------------------------------------------------------------------------
1 | # _PactSwift_ Core Contributor Expectations
2 |
3 | We are always looking for active, enthusiastic members of the developer community to become core contributors.
4 |
5 | We hope to harness the diversity of the iOS/macOS Developer community to build the _PactSwift_ into an essential tool for developers.
6 |
7 | ## How does one become a Core Contributor?
8 |
9 | Contributors who have displayed lasting commitment to the evolution and maintenance of this project will be invited to become Core Contributors. For instance, contributors who:
10 |
11 | - Love to help out other users with issues on GitHub
12 | - Continue to make _PactSwift_ a stable product and encourage features aligned with our [vision][vision].
13 |
14 | ## Core Contributors
15 |
16 | - Review pull requests using the "Review Changes" feature in GitHub.
17 | - Merge pull requests we review, except for PRs where the author has push access.
18 | - Respond to issues and help others.
19 | - Own regressions caused by our own contributions and PR approvals.
20 | - Maintain consistent coding standards.
21 | - Inform other Core Contributors when critical fixes are merged so a release can be prepared.
22 | - Identify other community members who would be effective Core Contributors.
23 | - Ensure that new contributions fit into the [Vision][vision].
24 | - Adhere to the [Code of Conduct][code-of-conduct].
25 | - Keep external dependencies to a minimum.
26 | - Keep test coverage high and ensure up-to-date documentation.
27 | - Are polite, friendly and having fun contributing.
28 |
29 | ## Pull Request Ownership
30 |
31 | We work in a high-trust environment which implies that anyone and everyone is able to merge pull requests from the community. If the PR reviewer feels strongly about seeing a PR to completion, they should assign it to themselves and request necessary changes.
32 |
33 | ## Adding Dependencies
34 |
35 | We want to keep _PactSwift_ focused and robust. Avoid adding new dependencies to the code base unless absolutely necessary.
36 |
37 | [vision]: VISION.md
38 | [code-of-conduct]: ../CODE_OF_CONDUCT.md
--------------------------------------------------------------------------------
/Documentation/VISION.md:
--------------------------------------------------------------------------------
1 | # Our Vision
2 |
3 | _PactSwift_ automates the process of generating Pact contracts.
4 |
5 | _PactSwift_ provides a simple and easy to use framework in one's Swift or Objective-C project that creates workflows where Pact contracts are generated.
6 |
7 | _PactSwift_ will continue to evolve, in a measured way that extends its functionality to make it an indespensable tool for developers writing [Consumer Driven contracts][consumer-driven-contracts].
8 |
9 | [consumer-driven-contracts]: https://martinfowler.com/articles/consumerDrivenContracts.html
10 |
--------------------------------------------------------------------------------
/Documentation/images/04_destination_dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/04_destination_dir.png
--------------------------------------------------------------------------------
/Documentation/images/08_xcode_spm_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/08_xcode_spm_search.png
--------------------------------------------------------------------------------
/Documentation/images/09_xcode_spm_options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/09_xcode_spm_options.png
--------------------------------------------------------------------------------
/Documentation/images/10_xcode_spm_add_package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/10_xcode_spm_add_package.png
--------------------------------------------------------------------------------
/Documentation/images/11_xcode_carthage_xcframework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/11_xcode_carthage_xcframework.png
--------------------------------------------------------------------------------
/Documentation/images/12_xcode_scheme_env_setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/12_xcode_scheme_env_setup.png
--------------------------------------------------------------------------------
/Documentation/images/pact-swift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surpher/PactSwift/0746420a5ea9198294916e86db3c305cb5c0f169/Documentation/images/pact-swift.png
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Marko Justinek
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.
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "PactSwiftMockServer",
6 | "repositoryURL": "https://github.com/surpher/PactSwiftServer.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "12ecc92092ecd3640dcc2dcb98ce6b3d1f2d76f7",
10 | "version": "0.4.7"
11 | }
12 | }
13 | ]
14 | },
15 | "version": 1
16 | }
17 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "PactSwift",
7 |
8 | platforms: [
9 | .macOS(.v10_13),
10 | .iOS(.v12),
11 | .tvOS(.v12)
12 | ],
13 |
14 | products: [
15 | .library(
16 | name: "PactSwift",
17 | targets: ["PactSwift"]
18 | )
19 | ],
20 |
21 | dependencies: [
22 | .package(url: "https://github.com/surpher/PactSwiftServer.git", .exact("0.4.7"))
23 | ],
24 |
25 | targets: [
26 |
27 | // PactSwift
28 | .target(
29 | name: "PactSwift",
30 | dependencies: [
31 | .product(name: "PactSwiftMockServer", package: "PactSwiftServer"),
32 | ],
33 | path: "./Sources"
34 | ),
35 |
36 | // Tests
37 | .testTarget(
38 | name: "PactSwiftTests",
39 | dependencies: [
40 | "PactSwift"
41 | ],
42 | path: "./Tests"
43 | ),
44 |
45 | ],
46 |
47 | swiftLanguageVersions: [.v5]
48 |
49 | )
50 |
--------------------------------------------------------------------------------
/PactSwift.xcodeproj/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | // Created by ___FULLUSERNAME___ on ___DATE___.
8 | // Copyright © ___YEAR___ ___FULLUSERNAME___. All rights reserved.
9 | //
10 | // Permission to use, copy, modify, and/or distribute this software for any
11 | // purpose with or without fee is hereby granted, provided that the above
12 | // copyright notice and this permission notice appear in all copies.
13 | //
14 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
20 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 | //
22 |
23 |
24 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/Scripts/BuildPhases/lint-project:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # PactSwift
4 | #
5 | # Created by Marko Justinek on 26/3/20.
6 | # Copyright © 2020 Marko Justinek. All rights reserved.
7 | # Permission to use, copy, modify, and/or distribute this software for any
8 | # purpose with or without fee is hereby granted, provided that the above
9 | # copyright notice and this permission notice appear in all copies.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 | #
19 |
20 | set -eu
21 |
22 | echo "--- 🤖 Linting ${PROJECT_NAME} Project..."
23 |
24 | SCRIPT_DIR="${BASH_SOURCE[0]%/*}"
25 |
26 | echo "Setting the scripts dir to ${SCRIPT_DIR}"
27 |
28 | "${SCRIPT_DIR}"/validate-build-settings
29 | "${SCRIPT_DIR}"/validate-project-config
30 |
31 | echo "--- 👍 ${PROJECT_NAME} project successfully validated and linted."
32 |
--------------------------------------------------------------------------------
/Scripts/BuildPhases/lint-target:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # PactSwift
4 | #
5 | # Created by Marko Justinek on 26/3/20.
6 | # Copyright © 2020 Marko Justinek. All rights reserved.
7 | # Permission to use, copy, modify, and/or distribute this software for any
8 | # purpose with or without fee is hereby granted, provided that the above
9 | # copyright notice and this permission notice appear in all copies.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 | #
19 |
20 | set -eu
21 |
22 | echo "--- 🤖 Linting ${TARGET_NAME} Target Structure..."
23 |
24 | #### Variables
25 |
26 | #### Expecting for source files to be in ./Sources file (SPM file structure)
27 | TARGET_SRCROOT="${SRCROOT}/Sources"
28 |
29 | errors=()
30 |
31 | #### Script steps
32 |
33 | if [[ ! -z "${INFOPLIST_FILE}" && ! -f "${INFOPLIST_FILE}" ]]; then
34 | errors+=("error: Could not find Info.plist file "${INFOPLIST_FILE}" for target '${TARGET_NAME}'.")
35 | fi
36 |
37 | if [[ ! -d "${TARGET_SRCROOT}" ]]; then
38 | errors+=("error: Could not find root folder '${TARGET_SRCROOT}' for target '${TARGET_NAME}'.")
39 | fi
40 |
41 | if [ ${#errors[@]} -ne 0 ]; then
42 | for i in "${errors[@]}"; do
43 | echo $i
44 | done
45 | exit 1
46 | fi
47 |
48 | echo "--- 👍 Linting ${TARGET_NAME} successful!"
49 |
--------------------------------------------------------------------------------
/Scripts/BuildPhases/validate-build-settings:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # PactSwift
4 | #
5 | # Created by Marko Justinek on 26/3/20.
6 | # Copyright © 2020 Marko Justinek. All rights reserved.
7 | # Permission to use, copy, modify, and/or distribute this software for any
8 | # purpose with or without fee is hereby granted, provided that the above
9 | # copyright notice and this permission notice appear in all copies.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 | #
19 |
20 | set -eu
21 |
22 | echo "--- 🤖 Ensuring there are no build settings in Xcode project file."
23 |
24 | PBXPROJ_FILE_PATH="${PROJECT_FILE_PATH}/project.pbxproj"
25 | NUMBER_OF_BUILD_SETTINGS=`grep "buildSettings" "$PBXPROJ_FILE_PATH" | wc -l`
26 | NUMBER_OF_EMPTY_BUILD_SETTINGS=`grep -B 0 -A 1 "buildSettings" "$PBXPROJ_FILE_PATH" | grep "};" | wc -l`
27 |
28 | if [ $NUMBER_OF_BUILD_SETTINGS != $NUMBER_OF_EMPTY_BUILD_SETTINGS ]; then
29 | NUMBER_WITH_SETTINGS=`expr $NUMBER_OF_BUILD_SETTINGS - $NUMBER_OF_EMPTY_BUILD_SETTINGS`
30 |
31 | echo "error: Found ${NUMBER_WITH_SETTINGS} build settings in Xcode project file! Build settings should only be defined in ./Configurations/*.xcconfig files."
32 | exit 1
33 | fi
34 |
35 | echo "--- 👍 There are no build settings in Xcode project file."
36 |
--------------------------------------------------------------------------------
/Scripts/BuildPhases/validate-project-config:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # PactSwift
4 | #
5 | # Created by Marko Justinek on 26/3/20.
6 | # Copyright © 2020 Marko Justinek. All rights reserved.
7 | # Permission to use, copy, modify, and/or distribute this software for any
8 | # purpose with or without fee is hereby granted, provided that the above
9 | # copyright notice and this permission notice appear in all copies.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 | #
19 |
20 | set -eu
21 |
22 | echo "--- 🤖 Validating project config..."
23 |
24 | PROJECT_CONFIG_DIR="${SRCROOT}/Configurations"
25 |
26 | ### Validate top level project configuration
27 | if [[ ! -d "${PROJECT_CONFIG_DIR}" ]]; then
28 | echo "error: Could not find 'Configurations' folder for project '${PROJECT_NAME}'."
29 | exit 1
30 | fi
31 |
32 | echo "--- 👍 Project config validated."
33 |
--------------------------------------------------------------------------------
/Scripts/build_file_list_and_swiftlint:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # PactSwift
4 | #
5 | # Created by Marko Justinek on 26/3/20.
6 | # Copyright © 2020 Marko Justinek. All rights reserved.
7 | # Permission to use, copy, modify, and/or distribute this software for any
8 | # purpose with or without fee is hereby granted, provided that the above
9 | # copyright notice and this permission notice appear in all copies.
10 | #
11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 | #
19 |
20 | set -eu
21 |
22 | # Adds support for Apple Silicon brew directory
23 | export PATH="$PATH:/opt/homebrew/bin"
24 |
25 | SRCROOT=${SRCROOT:-"."}
26 | DERIVED_FILE_DIR=${DERIVED_FILE_DIR:-"."}
27 |
28 | if [ $# -ne 2 ]; then
29 | echo "usage: build_file_list_and_swiftlint project_name swiftlint_yml"
30 | exit 1
31 | fi
32 |
33 | echo "--- 🤖 Linting $SRCROOT/Sources/*.swift"
34 |
35 | if which swiftlint >/dev/null; then
36 | # Build a list of Swift files in the Sources directory
37 | find Sources -name \*.swift -exec echo "\$(SRCROOT)/"{} \; > $DERIVED_FILE_DIR/$1.xcfilelist
38 |
39 | # Update the xcfilelist if the list of Swift files has changed
40 | cmp --silent $SRCROOT/$1.xcfilelist $DERIVED_FILE_DIR/$1.xcfilelist || cp -f $DERIVED_FILE_DIR/$1.xcfilelist $SRCROOT/$1.xcfilelist
41 |
42 | # Run swiftlint (TODO: - swiftlint by iterating through the $1.xcfilelist)
43 | # swiftlint --config $2 -- #filename0 #filename1 #filename2 ...
44 | swiftlint --config $2
45 |
46 | # Output an empty derived file
47 | touch $DERIVED_FILE_DIR/swiftlint.txt
48 |
49 | # All hunky dory
50 | echo "--- 👍 .swift files linted"
51 | else
52 | echo "--- ⚠️ Swiftlint"
53 | echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
54 | fi
55 |
--------------------------------------------------------------------------------
/Scripts/carthage:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # carthage workaround
4 | # Usage example: ./carthage build --platform iOS
5 | #
6 | # Source(s):
7 | # - https://github.com/Carthage/Carthage/issues/3201
8 | # - https://github.com/Carthage/Carthage/issues/3019#issuecomment-665136323
9 | # - https://github.com/Carthage/Carthage/issues/3019#issuecomment-734415287
10 | #
11 |
12 | set -euo pipefail
13 |
14 | # Determine architecture of current machine
15 | ACTIVE_ARCH=$(uname -m)
16 |
17 | if [[ $ACTIVE_ARCH == "x86_64" ]]; then
18 |
19 | # If running on Intel machine, do the excluded architectures dance 💃🕺
20 |
21 | xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
22 | trap 'rm -f "$xcconfig"' INT TERM HUP EXIT
23 |
24 | echo "⚠️ NOTE: Using Carthage workaround script..."
25 |
26 | # For Xcode 12 and 13 make sure EXCLUDED_ARCHS is set to arm architectures otherwise
27 | # the build will fail on lipo due to duplicate architectures.
28 |
29 | CURRENT_XCODE_VERSION="$(xcodebuild -version | grep "Xcode" | cut -d' ' -f2 | cut -d'.' -f1)00"
30 | CURRENT_XCODE_BUILD=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3)
31 |
32 | echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_${CURRENT_XCODE_VERSION}__BUILD_${CURRENT_XCODE_BUILD} = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig
33 |
34 | echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_'${CURRENT_XCODE_VERSION}' = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_$(XCODE_VERSION_MAJOR)__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig
35 | echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig
36 |
37 | export XCODE_XCCONFIG_FILE="$xcconfig"
38 | carthage "$@"
39 |
40 | else
41 |
42 | # Running on arm64 machine so just use the plain carthage
43 | echo "⚠️ NOTE: Using plain vanilla Carthage..."
44 | carthage "$@"
45 |
46 | fi
47 |
48 |
--------------------------------------------------------------------------------
/Scripts/check_build_tools:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -eu
4 | set -o pipefail
5 |
6 | # Checking for SwiftLint
7 | if which swiftlint >/dev/null; then
8 | echo "👍 swiftLint installed"
9 | else
10 | echo "⚠️ Swiftlint"
11 | echo "warning: SwiftLint not installed, use 'brew install swiftlint' to install it."
12 | fi
13 |
14 | # Checking for xcbeautify
15 | if which xcbeautify >/dev/null; then
16 | echo "👍 xcbeautify installed"
17 | else
18 | echo "⚠️ xcbeautify"
19 | echo "warning: xcbeautify not installed, use 'brew install xcbeautify' to install it."
20 | fi
--------------------------------------------------------------------------------
/Scripts/prepare_build_tools:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | brew tap thii/xcbeautify https://github.com/thii/xcbeautify.git
4 | brew install xcbeautify
5 |
6 | if [[ "$CI" == false ]]; then
7 | brew install swiftlint
8 | fi
--------------------------------------------------------------------------------
/Scripts/run_tests:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -eu
4 | set -o pipefail
5 |
6 | # Overridable Environment
7 | SIMULATOR_NAME=${SIMULATOR_NAME:-'iPhone 14 Pro'}
8 | SCRIPTS_DIR="${BASH_SOURCE[0]%/*}"
9 |
10 | # Determine architecture of current machine
11 | ACTIVE_ARCH=$(uname -m)
12 |
13 | # Check for dependencies
14 | $SCRIPTS_DIR/check_build_tools
15 |
16 | # Carthage build
17 | echo "📦 Building as a Carthage dependency"
18 | if [[ $ACTIVE_ARCH == "x86_64" ]]; then
19 | ${SCRIPTS_DIR}/carthage build --no-skip-current --use-xcframeworks
20 | else
21 | carthage build --no-skip-current --use-xcframeworks
22 | fi
23 |
24 | # Build and test for SPM
25 | echo "📦 Verifying it works using Swift Package Manager"
26 |
27 | echo "ℹ️ Resolving package dependencies"
28 | xcodebuild -resolvePackageDependencies
29 |
30 | echo "🏗 Building"
31 | swift build | xcbeautify
32 |
33 | echo "🤖 Running tests"
34 | swift test | xcbeautify
35 |
36 | # Run iOS tests
37 | echo "📱 Running iOS tests"
38 | set -o pipefail && xcodebuild clean test -project PactSwift.xcodeproj -scheme PactSwift-iOS -destination "platform=iOS Simulator,name=${SIMULATOR_NAME}" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcbeautify
39 |
40 | # Run macOS tests
41 | echo "🖥 Running macOS tests"
42 | set -o pipefail && xcodebuild clean test -project PactSwift.xcodeproj -scheme PactSwift-macOS -destination "platform=macOS,arch=${ACTIVE_ARCH}" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES| xcbeautify
43 |
44 | # A-OK?
45 |
46 | echo "👍 All hunky dory!"
47 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/DateTime.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DateTime.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 13/2/22.
6 | // Copyright © 2022 Marko Justinek. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension ExampleGenerator {
12 |
13 | /// Generates an example for DateTime using a specific `Date`
14 | struct DateTime: ExampleGeneratorExpressible {
15 | internal let value: Any
16 | internal let generator: ExampleGenerator.Generator = .dateTime
17 | internal var rules: [String: AnyEncodable]?
18 |
19 | /// Generates an example value for DateTime using a specific `Date` for consumer tests
20 | ///
21 | /// - Parameters:
22 | /// - format: The format used for datetime
23 | /// - use: The `Date` object used in consumer tests
24 | ///
25 | public init(format: String, use date: Date) {
26 | self.value = date.formatted(format)
27 | self.rules = [
28 | "format": AnyEncodable(format),
29 | ]
30 | }
31 | }
32 |
33 | }
34 |
35 | // MARK: - Objective-C
36 |
37 | @objc(PFGeneratorDateTime)
38 | public class ObjcDateTime: NSObject, ObjcGenerator {
39 |
40 | let type: ExampleGeneratorExpressible
41 |
42 | /// Generates an example value for DateTime using a specific `Date` for consumer tests
43 | ///
44 | /// - Parameters:
45 | /// - format: The format used for datetime
46 | /// - use: The `Date` object used in consumer tests
47 | ///
48 | @objc(date: format:)
49 | public init(format: String, use date: Date) {
50 | type = ExampleGenerator.DateTime(format: format, use: date)
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/DateTimeExpression.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DateTimeExpression.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 5/3/22.
6 | // Copyright © 2022 Marko Justinek. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension ExampleGenerator {
12 |
13 | /// Generates a generator for DateTime using an expression
14 | ///
15 | /// Warning:
16 | /// Not all Pact impelmentations support this type of example generator!
17 | ///
18 | struct DateTimeExpression: ExampleGeneratorExpressible {
19 | internal let value: Any
20 | internal let generator: ExampleGenerator.Generator = .dateTime
21 | internal var rules: [String: AnyEncodable]?
22 |
23 | /// Generates an example generator for DateTime using an expression
24 | ///
25 | /// - Parameters:
26 | /// - expression: The expression provider should use when verifying
27 | /// - format: The date time format
28 | ///
29 | /// - Warning: Not all Pact implementations support this type of example generator!
30 | ///
31 | public init(expression: String, format: String) {
32 | self.value = Date().formatted(format)
33 | self.rules = [
34 | "format": AnyEncodable(format),
35 | "expression": AnyEncodable(expression),
36 | ]
37 | }
38 | }
39 |
40 | }
41 |
42 | // MARK: - Objective-C
43 |
44 | @objc(PFGeneratorDateTimeExpression)
45 | public class OjbcDateTimeExpression: NSObject, ObjcGenerator {
46 |
47 | let type: ExampleGeneratorExpressible
48 |
49 | /// Generates an example generator for DateTime using an expression
50 | ///
51 | /// - Parameters:
52 | /// - expression: The expression provider should use when verifying
53 | /// - format: The date time format
54 | ///
55 | /// - Warning: Not all Pact implementations support this type of example generator!
56 | ///
57 | @objc(expression: format:)
58 | public init(expression: String, format: String) {
59 | type = ExampleGenerator.DateTimeExpression(expression: expression, format: format)
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/ProviderStateGenerator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 15/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | extension ExampleGenerator {
21 |
22 | // Works with Matcher.FromProviderState(references: value:)
23 | struct ProviderStateGenerator: ExampleGeneratorExpressible {
24 | let value: Any
25 | let generator: ExampleGenerator.Generator = .providerState
26 | var rules: [String: AnyEncodable]?
27 |
28 | init(parameter: String, value: Any) {
29 | self.value = value
30 | self.rules = [
31 | "expression": AnyEncodable(parameter),
32 | "type": AnyEncodable(generator.rawValue),
33 | ]
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/RandomBool.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ExampleGenerator {
21 |
22 | /// Generates a random boolean value
23 | struct RandomBool: ExampleGeneratorExpressible {
24 | internal let value: Any = Bool.random()
25 | internal let generator: ExampleGenerator.Generator = .bool
26 | internal let rules: [String: AnyEncodable]? = nil
27 |
28 | /// Generates a random boolean value
29 | public init() { }
30 | }
31 |
32 | }
33 |
34 | // MARK: - Objective-C
35 |
36 | @objc(PFGeneratorRandomBool)
37 | public class ObjcRandomBool: NSObject, ObjcGenerator {
38 |
39 | let type: ExampleGeneratorExpressible = ExampleGenerator.RandomBool()
40 |
41 | /// Generates a random boolean value
42 | @objc public override init() {
43 | super.init()
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/RandomDate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ExampleGenerator {
21 |
22 | /// Generates a Date value from the current date either in ISO format or using the provided format string
23 | struct RandomDate: ExampleGeneratorExpressible {
24 | internal let value: Any
25 | internal let generator: ExampleGenerator.Generator = .date
26 | internal var rules: [String: AnyEncodable]?
27 |
28 | /// Generates a `Date` value from the current date either in ISO format or using the provided format string
29 | ///
30 | /// - Parameters:
31 | /// - format: The format of generated date
32 | ///
33 | public init(format: String? = nil) {
34 | self.value = Date.formattedDate(format: format, isoFormat: .date)
35 |
36 | if let format = format {
37 | self.rules = [
38 | "format": AnyEncodable(format),
39 | ]
40 | }
41 | }
42 | }
43 |
44 | }
45 |
46 | // MARK: - Objective-C
47 |
48 | @objc(PFGeneratorRandomDate)
49 | public class ObjcRandomDate: NSObject, ObjcGenerator {
50 |
51 | let type: ExampleGeneratorExpressible
52 |
53 | /// Generates a `Date` value from the current date either in ISO format or using the provided format string
54 | ///
55 | /// - Parameters:
56 | /// - format: The format of generated date
57 | ///
58 | @objc(format:)
59 | public init(format: String? = nil) {
60 | type = ExampleGenerator.RandomDate(format: format)
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/RandomDateTime.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ExampleGenerator {
21 |
22 | /// Generates a Date and Time (timestamp) value from the current date and time either in ISO format or using the provided format string
23 | struct RandomDateTime: ExampleGeneratorExpressible {
24 | internal let value: Any
25 | internal let generator: ExampleGenerator.Generator = .dateTime
26 | internal var rules: [String: AnyEncodable]?
27 |
28 | /// Generates a Date and Time (timestamp) value from the current date and time either in ISO format or using the provided format string
29 | ///
30 | /// - Parameters:
31 | /// - format: The format of generated timestamp
32 | ///
33 | public init(format: String? = nil) {
34 | self.value = Date.formattedDate(format: format, isoFormat: .dateTime)
35 |
36 | if let format = format {
37 | self.rules = [
38 | "format": AnyEncodable(format),
39 | ]
40 | }
41 | }
42 | }
43 |
44 | }
45 |
46 | // MARK: - Objective-C
47 |
48 | @objc(PFGeneratorRandomDateTime)
49 | public class ObjcRandomDateTime: NSObject, ObjcGenerator {
50 |
51 | let type: ExampleGeneratorExpressible
52 |
53 | /// Generates a Date and Time (timestamp) value from the current date and time either in ISO format or using the provided format string
54 | ///
55 | /// - Parameters:
56 | /// - format: The format of generated timestamp
57 | ///
58 | @objc(format:)
59 | public init(format: String? = nil) {
60 | type = ExampleGenerator.RandomDateTime(format: format)
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/ExampleGenerators/RandomDecimal.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ExampleGenerator {
21 |
22 | /// Generates a random decimal value (BigDecimal) with the provided number of digits
23 | struct RandomDecimal: ExampleGeneratorExpressible {
24 | internal let value: Any
25 | internal let generator: ExampleGenerator.Generator = .decimal
26 | internal var rules: [String: AnyEncodable]?
27 |
28 | /// Generates a random decimal value (BigDecimal) with the provided number of digits
29 | ///
30 | /// - Parameters:
31 | /// - digits: Number of digits of the generated `Decimal` value (max 9)
32 | ///
33 | /// - Precondition: `digits` is a positive value
34 | ///
35 | public init(digits: Int = 6) {
36 | let digits = digits < 9 ? digits : 9
37 | self.value = NumberHelper.randomDecimal(digits: digits)
38 | self.rules = [
39 | "digits": AnyEncodable(digits < 9 ? digits : 9),
40 | ]
41 | }
42 | }
43 |
44 | }
45 |
46 | private enum NumberHelper {
47 |
48 | static func randomDecimal(digits: Int) -> Decimal {
49 | var randomDecimal: String = ""
50 | (0.. String {
42 | let formatter = DateFormatter()
43 | formatter.dateFormat = format
44 | return formatter.string(from: self)
45 | }
46 |
47 | // MARK: - Static interface
48 |
49 | static func formattedDate(format: String?, isoFormat: ISOFormat) -> String {
50 | if let format = format {
51 | return Date().formatted(format)
52 | }
53 |
54 | let formatter = ISO8601DateFormatter()
55 | formatter.formatOptions = isoFormat.formatOptions
56 | return formatter.string(from: Date())
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/Sources/Extensions/Dictionary+PactSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 31/3/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | /// Merges two `Dictionary` objects and returns a `Dictionary`
19 | func merge(_ lhs: [Key: Value], with rhs: [Key: Value]) -> [Key: Value] {
20 | var result = lhs
21 | rhs.forEach { result[$0] = $1 }
22 | return result
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/Extensions/MockServer+Async.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Oliver Jones on 30/11/2022.
3 | // Copyright © 2022 Oliver Jones. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | #if canImport(_Concurrency) && compiler(>=5.7)
19 |
20 | import Foundation
21 | @_implementationOnly import PactSwiftMockServer
22 |
23 | extension MockServer {
24 |
25 | /// Spins up a mock server with expected interactions defined in the provided Pact
26 | ///
27 | /// - Parameters:
28 | /// - pact: The pact contract
29 | /// - protocol: HTTP protocol
30 | ///
31 | @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
32 | @discardableResult
33 | func setup(pact: Data, protocol: PactSwiftMockServer.TransferProtocol = .standard) async throws -> Int {
34 | try await withCheckedThrowingContinuation { continuation in
35 | self.setup(pact: pact, protocol: `protocol`) { result in
36 | continuation.resume(with: result)
37 | }
38 | }
39 | }
40 |
41 | /// Verifies all interactions passed to mock server
42 | ///
43 | /// By default pact files are written to `/tmp/pacts`.
44 | /// Use `PACT_OUTPUT_DIR` environment variable with absolute path to your custom path in schema `run` configuration.
45 | ///
46 | @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
47 | func verify() async throws -> Bool {
48 | try await withCheckedThrowingContinuation { continuation in
49 | self.verify { result in
50 | continuation.resume(with: result)
51 | }
52 | }
53 | }
54 |
55 | /// Finalises Pact tests by writing the pact contract file to disk
56 | ///
57 | /// - Parameters:
58 | /// - pact: The Pact contract to write
59 | /// - completion: A completion block called when setup completes
60 | ///
61 | @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
62 | func finalize(pact: Data) async throws -> String {
63 | try await withCheckedThrowingContinuation { continuation in
64 | self.finalize(pact: pact) { result in
65 | continuation.resume(with: result)
66 | }
67 | }
68 | }
69 |
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/Sources/Extensions/Sequence+PactSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/7/21.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | extension Sequence where Iterator.Element: Hashable {
21 |
22 | var unique: [Iterator.Element] {
23 | var seen: Set = []
24 | return filter { seen.insert($0).inserted }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Extensions/String+PactSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 27/10/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | extension String: PactPathParameter { }
21 |
22 | extension String {
23 |
24 | /// Returns the `UUID` given the `String` itself represents a valid UUID
25 | var uuid: UUID? {
26 | UUID(uuidString: self)
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Extensions/Task+Timeout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Oliver Jones on 1/12/2022.
3 | // Copyright © 2022 Oliver Jones. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | #if canImport(_Concurrency) && compiler(>=5.7)
19 |
20 | import Foundation
21 |
22 | @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
23 | extension Task where Failure == Error {
24 |
25 | // Start a new Task with a timeout. If the timeout expires before the operation is
26 | // completed then the task is cancelled and an error is thrown.
27 | @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
28 | init(priority: TaskPriority? = nil, timeout: TimeInterval, operation: @escaping @Sendable () async throws -> Success) {
29 | self = Task(priority: priority) {
30 | try await withThrowingTaskGroup(of: Success.self) { group -> Success in
31 | group.addTask(operation: operation)
32 | group.addTask {
33 | try await _Concurrency.Task.sleep(nanoseconds: UInt64(timeout * Double(NSEC_PER_SEC)))
34 | throw TimeoutError(interval: timeout)
35 | }
36 | guard let success = try await group.next() else {
37 | throw _Concurrency.CancellationError()
38 | }
39 | group.cancelAll()
40 | return success
41 | }
42 | }
43 | }
44 | }
45 |
46 | struct TimeoutError: LocalizedError {
47 | var interval: TimeInterval
48 | var errorDescription: String? { "Task timed out after \(interval) seconds" }
49 | }
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/Sources/Extensions/UUID+PactSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 16/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | extension UUID {
21 |
22 | /// Returns `UUID` as String with no hyphens, lowercased
23 | var uuidStringSimple: String {
24 | self.uuidString.replacingOccurrences(of: "-", with: "").lowercased()
25 | }
26 |
27 | /// Returns an RFC4122-compliant string created from the UUID, such as "385336e1-d647-44a8-8b1b-3dbf4a073416"
28 | var rfc4122String: String {
29 | uuidString.lowercased()
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Headers/PactSwift.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 26/3/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | #import
19 |
20 | //! Project version number for PactSwift.
21 | FOUNDATION_EXPORT double PactSwiftVersionNumber;
22 |
23 | //! Project version string for PactSwift.
24 | FOUNDATION_EXPORT const unsigned char PactSwiftVersionString[];
25 |
26 | // In this header, you should import all the public headers of your framework using statements like #import
27 |
--------------------------------------------------------------------------------
/Sources/Matchers/DecimalLike.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Mathes a `Decimal` value.
23 | ///
24 | /// - Parameters:
25 | /// - value: The value MockService should expect or respond with in your tests
26 | ///
27 | /// Use this matcher when you expect the type being returned by the API provider is a `Decimal`.
28 | ///
29 | /// ```
30 | /// [
31 | /// "foo": Matcher.DecimalLike(1234)
32 | /// ]
33 | /// ```
34 | ///
35 | struct DecimalLike: MatchingRuleExpressible {
36 | internal let value: Any
37 | internal let rules: [[String: AnyEncodable]] = [["match": AnyEncodable("decimal")]]
38 |
39 | // MARK: - Initializer
40 |
41 | /// Mathes a `Decimal` value.
42 | ///
43 | /// - parameter value: The value MockService should expect or respond with in your tests
44 | ///
45 | public init(_ value: Decimal) {
46 | self.value = value
47 | }
48 | }
49 |
50 | }
51 |
52 | // MARK: - Objective-C
53 |
54 | /// Mathes a `Decimal` value.
55 | ///
56 | /// Use this matcher when you expect the type being returned by the API provider is a `Decimal`.
57 | ///
58 | /// ```
59 | /// @{@"foo": [Matcher DecimalLike(1234)] }
60 | /// ```
61 | ///
62 | /// - Parameters:
63 | /// - value: The value MockService should expect or respond with
64 | ///
65 | @objc(PFMatcherDecimalLike)
66 | public class ObjcDecimalLike: NSObject, ObjcMatcher {
67 |
68 | let type: MatchingRuleExpressible
69 |
70 | /// Mathes a `Decimal` value.
71 | ///
72 | /// - Parameters:
73 | /// - value: The value MockService should expect or respond with
74 | ///
75 | @objc(value:)
76 | public init(value: Decimal) {
77 | self.type = Matcher.DecimalLike(value)
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/Sources/Matchers/EqualTo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Matches the API provided value varbatim.
23 | ///
24 | /// Use this matcher where you expect the exact type and value
25 | /// in the interaction between your consumer and your provider.
26 | ///
27 | /// ```
28 | /// // DSL
29 | /// [
30 | /// "foo": Matcher.EqualTo("bar"),
31 | /// "bar": Matcher.EqualTo(847)
32 | /// ]
33 | /// ```
34 | ///
35 | struct EqualTo: MatchingRuleExpressible {
36 |
37 | internal let value: Any
38 | internal let rules: [[String: AnyEncodable]] = [["match": AnyEncodable("equality")]]
39 |
40 | // MARK: - Initializers
41 |
42 | /// Matches the API provided value varbatim.
43 | ///
44 | /// - parameter value: The exact value that is expected
45 | ///
46 | public init(_ value: Any) {
47 | self.value = value
48 | }
49 | }
50 |
51 | }
52 |
53 | // MARK: - Objective-C
54 |
55 | @objc(PFMatcherEqualTo)
56 | public class ObjcEqualTo: NSObject, ObjcMatcher {
57 |
58 | let type: MatchingRuleExpressible
59 |
60 | /// Matches the API provided value varbatim.
61 | ///
62 | /// - parameter value: The exact value that is expected
63 | ///
64 | @objc(value:)
65 | public init(value: Any) {
66 | type = Matcher.EqualTo(value)
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/Matchers/IntegerLike.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Matches an `Int` type.
23 | ///
24 | /// Use this matcher where you expect an `Int` to be returned
25 | /// by your API provider.
26 | ///
27 | struct IntegerLike: MatchingRuleExpressible {
28 |
29 | internal let value: Any
30 | internal let rules: [[String: AnyEncodable]] = [["match": AnyEncodable("integer")]]
31 |
32 | // MARK: - Initializer
33 |
34 | /// Matches an `Int` type.
35 | ///
36 | /// - Parameters:
37 | /// - value: Value to use in tests
38 | ///
39 | public init(_ value: Int) {
40 | self.value = value
41 | }
42 | }
43 |
44 | }
45 |
46 | // MARK: - Objective-C
47 |
48 | @objc(PFMatcherIntegerLike)
49 | public class ObjcIntegerLike: NSObject, ObjcMatcher {
50 |
51 | let type: MatchingRuleExpressible
52 |
53 | /// Matches an `Int` type.
54 | ///
55 | /// - Parameters:
56 | /// - value: Value to use in tests
57 | ///
58 | @objc(value:)
59 | public init(value: Int) {
60 | type = Matcher.IntegerLike(value)
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/Matchers/MatchNull.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/10/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Matches a `null` value.
23 | struct MatchNull: MatchingRuleExpressible {
24 |
25 | internal let value: Any
26 | internal let rules: [[String: AnyEncodable]] = [["match": AnyEncodable("null")]]
27 |
28 | // MARK: - Initializer
29 |
30 | /// The value returned by API provider matches `null`.
31 | public init() {
32 | value = "pact_matcher_null"
33 | }
34 | }
35 |
36 | }
37 |
38 | // MARK: - Objective-C
39 |
40 | @objc(PFMatcherNull)
41 | public class ObjcMatchNull: NSObject, ObjcMatcher {
42 |
43 | let type: MatchingRuleExpressible = Matcher.MatchNull()
44 |
45 | /// The value returned by API provider matches `null`.
46 | @objc public override init() {
47 | super.init()
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Sources/Matchers/OneOf.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/7/21.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Defines a Pact matcher that validates against one of the provided values
23 | ///
24 | /// Case sensitive. Uses the first provided value in consumer tests. Removes duplicate values.
25 | /// Use this matcher when you're expecting API response values to fit an `enum` type.
26 | ///
27 | struct OneOf: MatchingRuleExpressible {
28 | internal let value: Any
29 | internal let pattern: String
30 |
31 | internal var rules: [[String: AnyEncodable]] {
32 | [
33 | [
34 | "match": AnyEncodable("regex"),
35 | "regex": AnyEncodable(pattern),
36 | ],
37 | ]
38 | }
39 |
40 | // MARK: - Initializer
41 |
42 | /// Matches one of the provided values
43 | ///
44 | /// - Parameters:
45 | /// - values: List of possible values
46 | ///
47 | /// Case sensitive. Uses the first provided value in the consumer test. Removes duplicated values.
48 | ///
49 | init(_ values: AnyHashable...) {
50 | self.init(values: values)
51 | }
52 |
53 | /// Matches one of the provided values
54 | ///
55 | /// - Parameters:
56 | /// - values: The array of possible values
57 | ///
58 | /// Case sensitive. Uses the first provided value in the consumer test. Removes duplicated values.
59 | ///
60 | public init(values: [AnyHashable]) {
61 | self.value = values.first as Any
62 | self.pattern = Self.regexed(values)
63 | }
64 |
65 | // MARK: - Private
66 |
67 | private static func regexed(_ values: [AnyHashable]) -> String {
68 | "^(\(values.unique.map { "\($0)" }.joined(separator: "|")))$"
69 | }
70 | }
71 |
72 | }
73 |
74 | // MARK: - Objective-C
75 |
76 | @objc(PFMatcherOneOf)
77 | public class ObjcOneOf: NSObject, ObjcMatcher {
78 |
79 | let type: MatchingRuleExpressible
80 |
81 | /// Matches one of the provided values
82 | ///
83 | /// - Parameters:
84 | /// - values: The array of possible values
85 | ///
86 | /// Case sensitive. Uses the first provided value in the consumer test. Removes duplicated values.
87 | ///
88 | @objc(oneOfFloat:)
89 | public init(values: [AnyHashable]) {
90 | type = Matcher.OneOf(values: values)
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/Sources/Matchers/SomethingLike.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension Matcher {
21 |
22 | /// Matches a `Type`.
23 | ///
24 | /// Use this matcher where you expect a specific `Type` to be
25 | /// returned by the API provider.
26 | ///
27 | /// ```
28 | /// [
29 | /// "foo": Matcher.SomethingLike("bar"), // Matches a `String`
30 | /// "bar": Matcher.SomethingLike(1) // Matches an `Int`
31 | /// ]
32 | /// ```
33 | ///
34 | struct SomethingLike: MatchingRuleExpressible {
35 | internal let value: Any
36 | internal let rules: [[String: AnyEncodable]] = [["match": AnyEncodable("type")]]
37 |
38 | // MARK: - Initializers
39 |
40 | /// Matches the provided `Type`.
41 | ///
42 | /// - Parameters:
43 | /// - value: Value to use in tests
44 | ///
45 | public init(_ value: Any) {
46 | self.value = value
47 | }
48 | }
49 |
50 | }
51 |
52 | // MARK: - Objective-C
53 |
54 | @objc(PFMatcherSomethingLike)
55 | public class ObjcSomethingLike: NSObject, ObjcMatcher {
56 |
57 | let type: MatchingRuleExpressible
58 |
59 | /// Matches the provided `Type`.
60 | ///
61 | /// - Parameters:
62 | /// - value: Value to use in tests
63 | ///
64 | @objc(value:)
65 | public init(value: Any) {
66 | type = Matcher.SomethingLike(value)
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/Model/AnyEncodable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 6/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | struct AnyEncodable: Encodable {
21 |
22 | private let _encode: (Encoder) throws -> Void
23 |
24 | init(_ value: T) {
25 | self._encode = { encoder in
26 | var container = encoder.singleValueContainer()
27 | try container.encode(value)
28 | }
29 | }
30 |
31 | // Passing a `nil` as a generic type is not allowed so we are piggy-backing off of String type.
32 | init(_ value: String?) {
33 | self._encode = { encoder in
34 | var container = encoder.singleValueContainer()
35 | (value != nil) ? try container.encode(value) : try container.encodeNil()
36 | }
37 | }
38 |
39 | func encode(to encoder: Encoder) throws {
40 | try _encode(encoder)
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Model/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 31/7/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// Contains constant values used across `PactSwift`
21 | enum Constants {
22 |
23 | /// The default value for timeout when running Pact tests
24 | static let kTimeout: TimeInterval = 10
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Model/EncodingError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 27/10/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | enum EncodingError: Error {
21 | case encodingFailure(Any?)
22 | case unknown
23 |
24 | var localizedDescription: String {
25 | switch self {
26 | case .encodingFailure(let message):
27 | var errorMessage = ["Error preparing pact!"]
28 | message.map { errorMessage.append(String(describing: $0)) }
29 | return errorMessage.joined(separator: " ")
30 |
31 | default:
32 | return "Error casting unknown type into an Encodable type!"
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Model/ErrorReportable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 20/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public typealias FileString = StaticString
21 |
22 | public protocol ErrorReportable {
23 |
24 | func reportFailure(_ message: String)
25 | func reportFailure(_ message: String, file: FileString, line: UInt)
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Model/ErrorReporter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 20/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 | import XCTest
20 |
21 | class ErrorReporter: ErrorReportable {
22 |
23 | /// Reports test failure in file and on line where this method is called
24 | func reportFailure(_ message: String) {
25 | XCTFail(message, file: #file, line: #line)
26 | }
27 |
28 | /// Reports test failure in provided file and on provided line
29 | func reportFailure(_ message: String, file: FileString, line: UInt) {
30 | XCTFail(message, file: file, line: line)
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Model/ExampleGeneratorExpressible.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | protocol ExampleGeneratorExpressible {
21 |
22 | var value: Any { get }
23 | var generator: ExampleGenerator.Generator { get }
24 | var rules: [String: AnyEncodable]? { get }
25 |
26 | }
27 |
28 | extension ExampleGeneratorExpressible {
29 |
30 | var attributes: [String: AnyEncodable] {
31 | var generatorAttributes: [String: AnyEncodable] = rules ?? [:]
32 | generatorAttributes["type"] = AnyEncodable(generator.rawValue)
33 |
34 | return generatorAttributes
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/Model/MatchingRuleExpressible.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | protocol MatchingRuleExpressible {
21 |
22 | var value: Any { get }
23 | var rules: [[String: AnyEncodable]] { get }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Model/Metadata.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 1/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | struct Metadata {
21 |
22 | let pactSpec = PactVersion("3.0.0")
23 | let pactSwift = PactVersion(pactSwiftVersion)
24 |
25 | struct PactVersion: Encodable {
26 | let version: String
27 |
28 | init(_ version: String) {
29 | self.version = version
30 | }
31 | }
32 |
33 | }
34 |
35 | extension Metadata: Encodable {
36 |
37 | enum CodingKeys: String, CodingKey {
38 | case pactSpec = "pactSpecification"
39 | case pactSwift
40 | }
41 |
42 | public func encode(to encoder: Encoder) throws {
43 | var container = encoder.container(keyedBy: CodingKeys.self)
44 | try container.encode(pactSpec, forKey: .pactSpec)
45 | try container.encode(pactSwift, forKey: .pactSwift)
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/Model/Pact.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 1/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | struct Pact: Encodable {
21 |
22 | private let metadata = Metadata()
23 |
24 | // MARK: - Properties
25 |
26 | let consumer: Pacticipant
27 | let provider: Pacticipant
28 |
29 | var interactions: [Interaction] = []
30 |
31 | // These are the top level required nodes of a Pact contract file
32 | var payload: [String: Any] {
33 | [
34 | "consumer": consumer.name,
35 | "provider": provider.name,
36 | "interactions": interactions,
37 | "metadata": metadata,
38 | ]
39 | }
40 |
41 | var data: Data? {
42 | do {
43 | let encoder = JSONEncoder()
44 | return try encoder.encode(self)
45 | } catch {
46 | Logger.log(message: error.localizedDescription)
47 | }
48 | return nil
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/Sources/Model/PactHTTPMethod.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 31/3/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// The HTTP method expected in the interaction
21 | @objc public enum PactHTTPMethod: Int {
22 | case GET
23 | case HEAD
24 | case POST
25 | case PUT
26 | case PATCH
27 | case DELETE
28 | case TRACE
29 | case CONNECT
30 | case OPTIONS
31 | }
32 |
33 | extension PactHTTPMethod {
34 |
35 | var method: String {
36 | switch self {
37 | case .GET: return "get"
38 | case .HEAD: return "head"
39 | case .POST: return "post"
40 | case .PUT: return "put"
41 | case .PATCH: return "patch"
42 | case .DELETE: return "delete"
43 | case .TRACE: return "trace"
44 | case .CONNECT: return "connect"
45 | case .OPTIONS: return "options"
46 | }
47 | }
48 |
49 | }
50 |
51 | extension PactHTTPMethod: Encodable {
52 |
53 | enum CodingKeys: CodingKey {
54 | case method
55 | }
56 |
57 | public func encode(to encoder: Encoder) throws {
58 | var container = encoder.singleValueContainer()
59 | try container.encode(method)
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/Sources/Model/PactInteractionElement.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | enum PactInteractionNode: String {
21 |
22 | case body
23 | case header
24 | case path
25 | case query
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Model/PactInteractionNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | enum PactInteractionElement: String {
21 |
22 | case body
23 | case headers
24 | case path
25 | case query
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Model/PactPathParameter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 27/10/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// A protocol defining a Type that can be used as a request's path parameter (eg: a RegexLike matcher)
21 | public protocol PactPathParameter { }
22 |
--------------------------------------------------------------------------------
/Sources/Model/PactSwiftVersion.swift:
--------------------------------------------------------------------------------
1 | // !!! WARNING: THIS FILE IS AUTOMATED - DO NOT CHANGE OR MOVE !!!
2 | let pactSwiftVersion = "1.1.0"
3 |
--------------------------------------------------------------------------------
/Sources/Model/Pacticipant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 1/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// An object representing a participant in the Pact contract.
21 | enum Pacticipant {
22 |
23 | case consumer(String)
24 | case provider(String)
25 |
26 | var name: String {
27 | switch self {
28 | case .consumer(let name),
29 | .provider(let name):
30 | return name
31 | }
32 | }
33 |
34 | }
35 |
36 | extension Pacticipant: Encodable {
37 |
38 | enum CodingKeys: CodingKey {
39 | case name
40 | }
41 |
42 | public func encode(to encoder: Encoder) throws {
43 | var container = encoder.container(keyedBy: CodingKeys.self)
44 | try container.encode(name, forKey: .name)
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/Model/ProviderState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 2/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// Object describing expected provider state for an interaction
21 | public struct ProviderState: Encodable {
22 |
23 | let name: String
24 | let params: [String: String]
25 |
26 | /// Object describing expected provider state for an interaction
27 | ///
28 | /// - parameter description: The description of the state
29 | /// - parameter params: The `Key` `Value` pair of the expected state (eg: `"user_id": "1"`)
30 | ///
31 | public init(description: String, params: [String: String]) {
32 | self.name = description
33 | self.params = params
34 | }
35 |
36 | }
37 |
38 | extension ProviderState: Equatable {
39 |
40 | static public func ==(lhs: ProviderState, rhs: ProviderState) -> Bool {
41 | lhs.name == rhs.name && lhs.params == rhs.params
42 | }
43 |
44 | }
45 |
46 | // MARK: - Objective-C
47 | /*!
48 | @brief Object describing expected provider state for an interaction
49 |
50 | @discussion This object holds information about the provider state and specific parameters that are required for the specific provider state.
51 |
52 | To use it, simply call @c[[ProviderState alloc] description:@"user exists" params:@{@"id": @"abc123"}];
53 |
54 | @param description Description of the provider state
55 |
56 | @param params A dictionary of parameters describing data for the given state
57 | */
58 | @objc(ProviderState)
59 | public final class ObjCProviderState: NSObject {
60 |
61 | let state: ProviderState
62 |
63 | @objc(initWithDescription:params:)
64 | public init(description: String, params: [String: String]) {
65 | state = ProviderState(description: description, params: params)
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Sources/Model/ProviderVerifier+Error.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 23/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ProviderVerifier {
21 |
22 | // A bridge to PactSwiftMockServer provider verification errors
23 | enum VerificationError: Error {
24 | case error(String)
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Model/ProviderVerifier+Provider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 21/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | public extension ProviderVerifier {
21 |
22 | /// The provider being verified
23 | struct Provider {
24 |
25 | /// The port of provider being verified
26 | let port: Int
27 |
28 | /// URL of the provider being verified
29 | let url: URL?
30 |
31 | /// The provider being verified
32 | public init(url: URL? = nil, port: Int) {
33 | self.url = url
34 | self.port = port
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Model/Response.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 31/3/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | /// An object representing an API response in Pact Specification Version 3.0
19 | public struct Response {
20 |
21 | var statusCode: Int
22 | var headers: [String: Any]?
23 |
24 | private let bodyEncoder: (Encoder) throws -> Void
25 |
26 | }
27 |
28 | extension Response: Encodable {
29 |
30 | enum CodingKeys: String, CodingKey {
31 | case statusCode = "status"
32 | case headers
33 | case body
34 | case matchingRules
35 | case generators
36 | }
37 |
38 | /// Creates an object representing a network `Response`
39 | /// - Parameters:
40 | /// - statusCode: The status code of the API response
41 | /// - headers: Headers of the API response
42 | /// - body: Optional body in the API response
43 | ///
44 | init(statusCode: Int, headers: [String: Any]? = nil, body: Any? = nil) throws {
45 | self.statusCode = statusCode
46 | self.headers = headers
47 |
48 | let bodyValues = try Toolbox.process(element: body, for: .body)
49 | let headerValues = try Toolbox.process(element: headers, for: .header)
50 |
51 | self.bodyEncoder = {
52 | var container = $0.container(keyedBy: CodingKeys.self)
53 | try container.encode(statusCode, forKey: .statusCode)
54 | if let header = headerValues?.node { try container.encode(header, forKey: .headers) }
55 | if let encodableBody = bodyValues?.node { try container.encode(encodableBody, forKey: .body) }
56 | if let matchingRules = Toolbox.merge(body: bodyValues?.rules, header: headerValues?.rules) {
57 | try container.encode(matchingRules, forKey: .matchingRules)
58 | }
59 | if let generators = Toolbox.merge(body: bodyValues?.generators, header: headerValues?.generators) {
60 | try container.encode(generators, forKey: .generators)
61 | }
62 | }
63 | }
64 |
65 | public func encode(to encoder: Encoder) throws {
66 | try bodyEncoder(encoder)
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/Model/Toolbox.swift:
--------------------------------------------------------------------------------
1 | // Created by Marko Justinek on 20/10/20.
2 | // Copyright © 2020 Marko Justinek. All rights reserved.
3 | //
4 | // Permission to use, copy, modify, and/or distribute this software for any
5 | // purpose with or without fee is hereby granted, provided that the above
6 | // copyright notice and this permission notice appear in all copies.
7 | //
8 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
14 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 | //
16 |
17 | import Foundation
18 |
19 | enum Toolbox {
20 |
21 | /// Merges the Pact top level elements into one dictionary thac can be Encoded
22 | /// - Parameters:
23 | /// - body: The PactBuilder processed object representing interaction's body
24 | /// - query: The PactBuilder processed object representing interaction's query
25 | /// - header: The PactBuilder processed object representing interaction's header
26 | /// - path: The PactBuilder processed object representing request path
27 | ///
28 | static func merge(body: AnyEncodable?, query: AnyEncodable? = nil, header: AnyEncodable? = nil, path: AnyEncodable? = nil) -> [String: AnyEncodable]? {
29 | var merged: [String: AnyEncodable] = [:]
30 |
31 | if let header = header {
32 | merged["header"] = header
33 | }
34 |
35 | if let body = body {
36 | merged["body"] = body
37 | }
38 |
39 | if let query = query {
40 | merged["query"] = query
41 | }
42 |
43 | if let path = path {
44 | merged["path"] = path
45 | }
46 |
47 | return merged.isEmpty ? nil : merged
48 | }
49 |
50 | /// Runs the `Any` type through PactBuilder and returns a Pact tuple
51 | /// - Parameters:
52 | /// - element: The object to process through PactBuilder
53 | /// - interactionElement: The network interaction element the object relates to
54 | ///
55 | static func process(element: Any?, for interactionElement: PactInteractionNode) throws -> (node: AnyEncodable?, rules: AnyEncodable?, generators: AnyEncodable?)? {
56 | if let element = element {
57 | do {
58 | let encodedElement = try PactBuilder(with: element, for: interactionElement).encoded()
59 | return (node: encodedElement.node, rules: encodedElement.rules, generators: encodedElement.generators)
60 | } catch {
61 | throw error
62 | }
63 | }
64 |
65 | return nil
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Sources/Model/TransferProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 31/7/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | #if compiler(>=5.5)
21 | // This is ridiculous! This works when building on macOS 11+.
22 | @_implementationOnly import PactSwiftMockServer
23 | #else
24 | import PactSwiftMockServer
25 | #endif
26 |
27 | /// Defines the transfer protocol on which `MockService` runs.
28 | @objc public enum TransferProtocol: Int {
29 | case standard
30 | case secure
31 |
32 | var bridge: PactSwiftMockServer.TransferProtocol {
33 | switch self {
34 | case .standard: return .standard
35 | case .secure: return .secure
36 | }
37 | }
38 | }
39 |
40 | extension TransferProtocol {
41 |
42 | /// HTTP Transfer protocol
43 | var `protocol`: String {
44 | switch self {
45 | case .standard: return "http"
46 | case .secure: return "https"
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Sources/Model/VersionSelector.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 19/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// Provides a way to configure which pacts the provider verifies.
21 | public struct VersionSelector: Codable, Equatable {
22 |
23 | // MARK: - Properties
24 |
25 | /// The name of the tag which applies to the pacticipant versions of the pacts to verify
26 | let tag: String
27 |
28 | /// Whether or not to verify only the pact that belongs to the latest application version
29 | let latest: Bool
30 |
31 | /// A fallback tag if a pact for the specified `tag` does not exist
32 | let fallbackTag: String?
33 |
34 | /// Filter pacts by the specified consumer
35 | ///
36 | /// When omitted, all consumers are included.
37 | let consumer: String?
38 |
39 | // MARK: - Initialization
40 |
41 | /// Defines a version configuration for which pacts the provider verifies
42 | ///
43 | /// - Parameters:
44 | /// - tag: The version `tag` name of the consumer to verify
45 | /// - fallbackTag: The version `tag` to use if the initial `tag` does not exist
46 | /// - latest: Whether to verify only the pact belonging to the latest application version
47 | /// - consumer: Filter pacts by the specified consumer
48 | ///
49 | /// See [https://docs.pact.io/selectors](https://docs.pact.io/selectors) for more context.
50 | ///
51 | public init(tag: String, fallbackTag: String? = nil, latest: Bool = true, consumer: String? = nil) {
52 | self.tag = tag
53 | self.fallbackTag = fallbackTag
54 | self.latest = latest
55 | self.consumer = consumer
56 | }
57 |
58 | }
59 |
60 | // MARK: - Internal
61 |
62 | extension VersionSelector {
63 |
64 | /// Converts to JSON string
65 | ///
66 | /// - Returns: A `String` representing `ProviderVerifier` in JSON format
67 | ///
68 | func toJSONString() throws -> String {
69 | let jsonEncoder = JSONEncoder()
70 | let jsonData = try jsonEncoder.encode(self)
71 | guard let jsonString = String(data: jsonData, encoding: .utf8) else {
72 | throw ProviderVerifier.VerificationError.error("Invalid consumer version selector specified: \(self)")
73 | }
74 |
75 | return jsonString
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/Sources/Model/WIPPacts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 24/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | /// The configuration used when verifying WIP pacts
21 | public struct WIPPacts {
22 |
23 | /// The date from which the changed pacts are to be included
24 | let sinceDate: Date
25 |
26 | /// The provider
27 | let providerVersion: String
28 |
29 | /// Configuration for verifying WIP pacts
30 | ///
31 | /// - Parameters:
32 | /// - since: The date from which the WIP pacts are to be included in verification
33 | /// - providerVersion: The provider version being verified
34 | ///
35 | /// See [Work in Progress pacts](https://docs.pact.io/pact_broker/advanced_topics/wip_pacts/) for more
36 |
37 | /// - Warning: The `providerVersion` value set in the `VerificationResult` object is used if provided
38 | ///
39 | public init(since date: Date, providerVersion: String) {
40 | self.sinceDate = date
41 | self.providerVersion = providerVersion
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/ProviderVerifier.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 20/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 | import XCTest
20 |
21 | #if compiler(>=5.5)
22 | @_implementationOnly import PactSwiftMockServer
23 | #else
24 | import PactSwiftMockServer
25 | #endif
26 |
27 | /// Entry point for provider verification
28 | public final class ProviderVerifier {
29 |
30 | let verifier: ProviderVerifying
31 | private let errorReporter: ErrorReportable
32 |
33 | /// Initializes a `Verifier` object for provider verification
34 | public convenience init() {
35 | self.init(verifier: Verifier(), errorReporter: ErrorReporter())
36 | }
37 |
38 | /// Initializes a `Verifier` object
39 | ///
40 | /// - Parameters:
41 | /// - verifier: The verifier object handling provider verification
42 | /// - errorReporter: Error reporting or intercepting object
43 | ///
44 | /// This initializer is marked `internal` for testing purposes!
45 | ///
46 | internal init(verifier: ProviderVerifying, errorReporter: ErrorReportable? = nil) {
47 | self.verifier = verifier
48 | self.errorReporter = errorReporter ?? ErrorReporter()
49 | }
50 |
51 | /// Executes provider verification test
52 | ///
53 | /// - Parameters:
54 | /// - options: Flags and args to use when verifying a provider
55 | /// - file: The file in which to report the error in
56 | /// - line: The line on which to report the error on
57 | /// - completionBlock: Completion block executed at the end of verification
58 | ///
59 | /// - Returns: A `Result` where error describes the failure
60 | ///
61 | @discardableResult
62 | public func verify(options: Options, file: FileString? = #file, line: UInt? = #line, completionBlock: (() -> Void)? = nil) -> Result {
63 | switch verifier.verifyProvider(options: options.args) {
64 | case .success(let value):
65 | completionBlock?()
66 | return .success(value)
67 | case .failure(let error):
68 | failWith(error.description, file: file, line: line)
69 | completionBlock?()
70 | return .failure(VerificationError.error(error.description))
71 | }
72 | }
73 |
74 | }
75 |
76 | // MARK: - Private
77 |
78 | private extension ProviderVerifier {
79 |
80 | /// Fail the test and raise the failure in `file` at `line`
81 | func failWith(_ message: String, file: FileString? = nil, line: UInt? = nil) {
82 | if let file = file, let line = line {
83 | errorReporter.reportFailure(message, file: file, line: line)
84 | } else {
85 | errorReporter.reportFailure(message)
86 | }
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/Sources/Toolbox/Logger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/8/2022.
3 | // Copyright © 2022 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 | import os.log
20 |
21 | enum Logger {
22 |
23 | /// Logs Pact related messages.
24 | ///
25 | /// Looks for environment variable `PACT_ENABLE_LOGGING = "all"`. Can be set in project's scheme. Uses `os_log` on Apple platforms.
26 | ///
27 | /// - Parameters:
28 | /// - message: The message to log
29 | /// - data: Data to log
30 | ///
31 | static func log(message: String, data: Data? = nil) {
32 | guard case .all = PactLoggingLevel(value: ProcessInfo.processInfo.environment["PACT_ENABLE_LOGGING"]) else {
33 | return
34 | }
35 |
36 | let stringData = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
37 |
38 | if #available(iOS 10, OSX 10.14, *) {
39 | os_log(
40 | "PactSwift: %{private}s",
41 | log: .default,
42 | type: .default,
43 | "\(message): \(stringData)"
44 | )
45 | } else {
46 | print(message: "PactSwift: \(message)\n\(stringData)")
47 | }
48 | }
49 |
50 | }
51 |
52 | // MARK: - Private
53 |
54 | private extension Logger {
55 |
56 | static func print(message: String) {
57 | debugPrint(message)
58 | }
59 |
60 | enum PactLoggingLevel: String {
61 | case all
62 | case disabled
63 |
64 | init(value: String?) {
65 | switch value {
66 | case "all": self = .all
67 | default: self = .disabled
68 | }
69 | }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/Sources/Toolbox/PactFileManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 9/8/2022.
3 | // Copyright © 2022 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | enum PactFileManager {
21 |
22 | /// Where Pact contracts are written to.
23 | ///
24 | /// macOS:
25 | ///
26 | /// Running tests for macOS it will default to app's Documents folder:
27 | ///
28 | /// (eg: `~/Library/Containers/au.com.pact-foundation.Pact-macOS-Example/Data/Documents`)
29 | ///
30 | /// If testing a sandboxed macOS app, this is the default location and it can not be overwritten.
31 | /// If testing a macOS app that is not sandboxed, define a `PACT_OUTPUT_DIR` Environment Variable (in the scheme)
32 | /// with the path to where you want Pact contracts to be written to.
33 | ///
34 | /// iOS/tvOS or non-Xcode project:
35 | ///
36 | /// Default location where Pact contracts are written is `/tmp/pacts` and can be overwritten
37 | /// with a `PACT_OUTPUT_DIR` environment variable set to an absolute path (eg: `$(PROJECT_DIR)/tmp/pacts`).
38 | ///
39 | static var pactDirectoryPath: String {
40 | #if os(macOS) || os(OSX)
41 | let defaultPath = NSHomeDirectory() + "/Documents"
42 | if isSandboxed {
43 | return defaultPath
44 | }
45 | return ProcessInfo.processInfo.environment["PACT_OUTPUT_DIR"] ?? defaultPath
46 | #else
47 | return ProcessInfo.processInfo.environment["PACT_OUTPUT_DIR"] ?? "/tmp/pacts"
48 | #endif
49 | }
50 |
51 | /// Returns true if the directory where Pact contracts are set to be written to exists.
52 | /// If it does not exists, it attempts to create it and if successful, returns true.
53 | ///
54 | static func isPactDirectoryAvailable() -> Bool {
55 | if FileManager.default.fileExists(atPath: pactDirectoryPath) == false {
56 | do {
57 | try FileManager.default.createDirectory(at: pactDirectoryURL, withIntermediateDirectories: true, attributes: nil)
58 | } catch let error as NSError {
59 | debugPrint("Directory \(pactDirectoryURL) could not be created! \(error.localizedDescription)")
60 | return false
61 | }
62 | }
63 | return true
64 | }
65 |
66 | }
67 |
68 | // MARK: - Private
69 |
70 | private extension PactFileManager {
71 |
72 | static var pactDirectoryURL: URL {
73 | URL(fileURLWithPath: pactDirectoryPath, isDirectory: true)
74 | }
75 |
76 | /// Returns true if app is sandboxed
77 | static var isSandboxed: Bool {
78 | let environment = ProcessInfo.processInfo.environment
79 | return environment["APP_SANDBOX_CONTAINER_ID"] != nil
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/DateTimeExpressionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DateTimeExpressionTests.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 5/3/22.
6 | // Copyright © 2022 Marko Justinek. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | @testable import PactSwift
12 |
13 | class DateTimeExpressionTests: XCTestCase {
14 |
15 | func testDateTimeExpressionExampleGenerator() throws {
16 | let testFormat = "dd.MM.yyyy HH:mm:ss"
17 | let testExpression = "tomorrow 5pm"
18 | let sut = ExampleGenerator.DateTimeExpression(expression: testExpression, format: testFormat)
19 |
20 | XCTAssertEqual(sut.generator, .dateTime)
21 |
22 | let attributes = try XCTUnwrap(sut.rules)
23 | XCTAssertTrue(
24 | ["format", "expression"].allSatisfy { keyValue in
25 | attributes.contains { key, _ in
26 | key == keyValue
27 | }
28 | }
29 | )
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/DateTimeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DateTimeTests.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 13/2/22.
6 | // Copyright © 2022 Marko Justinek. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | @testable import PactSwift
12 |
13 | class DateTimeTests: XCTestCase {
14 |
15 | func testDateTimeExampleGenerator() throws {
16 | let testDate = Date()
17 | let testFormat = "YYYY-MM-DD HH:mm"
18 | let sut = ExampleGenerator.DateTime(format: testFormat, use: testDate)
19 |
20 | XCTAssertEqual(sut.generator, .dateTime)
21 |
22 | let resultValue = try XCTUnwrap(sut.value as? String)
23 | let resultDate = try XCTUnwrap(DateHelper.dateFrom(string: resultValue, format: testFormat))
24 | // Assert using the same format due to loss of accuracy using a limited datetime format
25 | XCTAssertEqual(testDate.formatted(testFormat), resultDate.formatted(testFormat))
26 |
27 | let attributes = try XCTUnwrap(sut.rules)
28 | XCTAssertTrue(attributes.contains { key, _ in
29 | key == "format"
30 | })
31 |
32 | let resultFormat = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
33 | XCTAssertEqual(resultFormat.format, testFormat)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/ProviderStateGeneratorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 15/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class ProviderStateGeneratorTests: XCTestCase {
23 |
24 | let sut = ExampleGenerator.ProviderStateGenerator(parameter: "test-parameter", value: "test-value")
25 |
26 | func testProviderGenerator() throws {
27 | XCTAssertEqual(sut.generator, .providerState)
28 | }
29 |
30 | func testProviderGenerator_WithExpression() throws {
31 | let valueResult = try XCTUnwrap((sut.value as Any) as? String)
32 | XCTAssertEqual(valueResult, "test-value")
33 |
34 | let attributes = try XCTUnwrap(sut.rules)
35 | XCTAssertTrue(attributes.contains { key, _ in
36 | key == "expression"
37 | })
38 | }
39 |
40 | func testProviderGenerator_WithType() throws {
41 | let attributes = try XCTUnwrap(sut.rules)
42 | XCTAssertTrue(attributes.contains { key, value in
43 | key == "type"
44 | })
45 | }
46 |
47 | func testProviderGenerator_SetsRules() throws {
48 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
49 |
50 | XCTAssertEqual(result.type, "ProviderState")
51 | XCTAssertEqual(result.expression, "test-parameter")
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomBooleanTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 16/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomBooleanTests: XCTestCase {
23 |
24 | func testBooleanExampleGenerator() {
25 | let sut = ExampleGenerator.RandomBool()
26 | XCTAssertTrue(sut.value is Bool)
27 | XCTAssertEqual(sut.generator, .bool)
28 | XCTAssertNil(sut.rules)
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomDateTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomDateTests: XCTestCase {
23 |
24 | func testRandomDate() {
25 | let sut = ExampleGenerator.RandomDate()
26 |
27 | XCTAssertEqual(sut.generator, .date)
28 | XCTAssertNil(sut.rules)
29 | XCTAssertNotNil(DateHelper.dateFrom(isoString: try XCTUnwrap(sut.value as? String), isoFormat: [.withFullDate, .withDashSeparatorInDate]))
30 | }
31 |
32 | func testRandomDate_WithFormat() throws {
33 | let testFormat = "dd-MM-yyyy"
34 | let sut = ExampleGenerator.RandomDate(format: testFormat)
35 |
36 | let attributes = try XCTUnwrap(sut.rules)
37 | XCTAssertTrue(attributes.contains { key, _ in
38 | key == "format"
39 | })
40 | XCTAssertEqual(sut.generator, .date)
41 | XCTAssertNotNil(DateHelper.dateFrom(string: try XCTUnwrap(sut.value as? String), format: testFormat))
42 | }
43 |
44 | func testRandomDate_SetsRules() throws {
45 | let testFormat = "dd-MM-yyyy"
46 | let sut = ExampleGenerator.RandomDate(format: testFormat)
47 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
48 |
49 | XCTAssertEqual(result.format, testFormat)
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomDateTimeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomDateTimeTests: XCTestCase {
23 |
24 | func testRandomDateTime() {
25 | let sut = ExampleGenerator.RandomDateTime()
26 |
27 | XCTAssertEqual(sut.generator, .dateTime)
28 | XCTAssertNil(sut.rules)
29 | XCTAssertNotNil(DateHelper.dateFrom(isoString: try XCTUnwrap(sut.value as? String), isoFormat: [.withFullDate, .withFullTime]))
30 | }
31 |
32 | func testRandomDateTime_WithFormat() throws {
33 | let testFormat = "yyyy/MM/dd - HH:mm:ss.S"
34 | let sut = ExampleGenerator.RandomDateTime(format: testFormat)
35 |
36 | let attributes = try XCTUnwrap(sut.rules)
37 | XCTAssertTrue(attributes.contains { key, _ in
38 | key == "format"
39 | })
40 | XCTAssertEqual(sut.generator, .dateTime)
41 | XCTAssertNotNil(DateHelper.dateFrom(string: try XCTUnwrap(sut.value as? String), format: testFormat))
42 | }
43 |
44 | func testRandomDateTime_SetsRules() throws {
45 | let testFormat = "yyyy/MM/dd - HH:mm:ss.S"
46 | let sut = ExampleGenerator.RandomDateTime(format: testFormat)
47 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
48 |
49 | XCTAssertEqual(result.format, testFormat)
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomDecimalTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomDecimalTests: XCTestCase {
23 |
24 | func testRandomDecimal() throws {
25 | let sut = ExampleGenerator.RandomDecimal()
26 |
27 | let attributes = try XCTUnwrap(sut.rules)
28 | XCTAssertTrue(attributes.contains { key, _ in
29 | key == "digits"
30 | })
31 | XCTAssertEqual(sut.generator, .decimal)
32 | let decimalValue = try XCTUnwrap(sut.value as? Decimal)
33 | XCTAssertEqual(String(describing: decimalValue).count, 6)
34 | }
35 |
36 | func testRandomDecimal_WithDigits() throws {
37 | let sut = ExampleGenerator.RandomDecimal(digits: 12)
38 |
39 | let attributes = try XCTUnwrap(sut.rules)
40 | XCTAssertTrue(attributes.contains { key, _ in
41 | key == "digits"
42 | })
43 | XCTAssertEqual(sut.generator, .decimal)
44 | let decimalValue = try XCTUnwrap(sut.value as? Decimal)
45 |
46 | // Expecting 9 digits as it's the set as the cap in ExampleGenerator.Decimal
47 | XCTAssertEqual(String(describing: decimalValue).count, 9)
48 | }
49 |
50 | func testRandomDecimal_SetsRules() throws {
51 | let sut = ExampleGenerator.RandomDecimal(digits: 12)
52 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
53 |
54 | // Expecting a key `digits` with value 9
55 | XCTAssertEqual(result.digits, 9)
56 | }
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomHexadecimalTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomHexadecimalTests: XCTestCase {
23 |
24 | func testRandomHexadecimal() throws {
25 | let sut = ExampleGenerator.RandomHexadecimal()
26 |
27 | XCTAssertEqual(sut.generator, .hexadecimal)
28 |
29 | let attributes = try XCTUnwrap(sut.rules)
30 | XCTAssertTrue(attributes.contains { key, _ in
31 | key == "digits"
32 | })
33 |
34 | let hexValue = try XCTUnwrap(sut.value as? String)
35 | XCTAssertEqual(hexValue.count, 8)
36 | }
37 |
38 | func testRandomHexadecimal_WithDigits() throws {
39 | let sut = ExampleGenerator.RandomHexadecimal(digits: 16)
40 |
41 | XCTAssertEqual(sut.generator, .hexadecimal)
42 |
43 | let attributes = try XCTUnwrap(sut.rules)
44 | XCTAssertTrue(attributes.contains { key, _ in
45 | key == "digits"
46 | })
47 |
48 | let hexValue = try XCTUnwrap(sut.value as? String)
49 | XCTAssertEqual(hexValue.count, 16)
50 | }
51 |
52 | func testRandomHexadecimal_SetsRules() throws {
53 | let sut = ExampleGenerator.RandomHexadecimal(digits: 16)
54 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
55 |
56 | // Expecting a key `digits` with value 16
57 | XCTAssertEqual(result.digits, 16)
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomIntTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 16/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomIntTests: XCTestCase {
23 |
24 | func testRandomIntExampleGenerator() throws {
25 | let expectedKeys = ["min", "max"]
26 | let sut = ExampleGenerator.RandomInt(min: -4231, max: 64210)
27 |
28 | let attributes = try XCTUnwrap(sut.rules)
29 | XCTAssertTrue((sut.value as Any) is Int)
30 | XCTAssertEqual(sut.generator, .int)
31 | XCTAssertTrue(attributes.allSatisfy { key, value in expectedKeys.contains(key) })
32 | XCTAssertTrue((-4231...64210).contains(sut.value as! Int))
33 | }
34 |
35 | func testRandomInt_SetsRules() throws {
36 | let sut = ExampleGenerator.RandomInt(min: -4231, max: 2147483647)
37 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
38 |
39 | XCTAssertEqual(result.min, -4231)
40 | XCTAssertEqual(result.max, 2147483647)
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomStringTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 18/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomStringTests: XCTestCase {
23 |
24 | func testRandomString() throws {
25 | let sut = ExampleGenerator.RandomString()
26 |
27 | let attributes = try XCTUnwrap(sut.rules)
28 | XCTAssertTrue(attributes.contains { key, _ in
29 | key == "size"
30 | })
31 | XCTAssertEqual(sut.generator, .string)
32 | let stringValue = try XCTUnwrap(sut.value as? String)
33 | XCTAssertEqual(stringValue.count, 20)
34 | }
35 |
36 | func testRandomString_WithSize() throws {
37 | let sut = ExampleGenerator.RandomString(size: 1145)
38 |
39 | let attributes = try XCTUnwrap(sut.rules)
40 | XCTAssertTrue(attributes.contains { key, _ in
41 | key == "size"
42 | })
43 | XCTAssertEqual(sut.generator, .string)
44 | let stringValue = try XCTUnwrap(sut.value as? String)
45 | XCTAssertEqual(stringValue.count, 1145)
46 | }
47 |
48 | func testRandomRegex() throws {
49 | let sut = ExampleGenerator.RandomString(regex: #"\d{1,2}/\d{1,2}"#)
50 |
51 | let attributes = try XCTUnwrap(sut.rules)
52 | XCTAssertTrue(attributes.contains { key, _ in
53 | key == "regex"
54 | })
55 |
56 | XCTAssertEqual(sut.generator, .regex)
57 | }
58 |
59 | func testRandomString_SetsSizeRules() throws {
60 | let sut = ExampleGenerator.RandomString(size: 20)
61 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
62 |
63 | XCTAssertEqual(result.size, 20)
64 | }
65 |
66 | func testRandomString_SetsRegexRules() throws {
67 | let regex = #"\d{1,2}/\d{1,2}"#
68 | let sut = ExampleGenerator.RandomString(regex: regex)
69 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
70 |
71 | XCTAssertEqual(result.regex, regex)
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomTimeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomTimeTests: XCTestCase {
23 |
24 | func testRandomTime() throws {
25 | let sut = ExampleGenerator.RandomTime()
26 |
27 | XCTAssertEqual(sut.generator, .time)
28 | XCTAssertNil(sut.rules)
29 | let isoTime = try XCTUnwrap(sut.value as? String)
30 | XCTAssertNotNil(DateHelper.dateFrom(isoString: isoTime, isoFormat: [.withFullTime]))
31 | }
32 |
33 | func testRandomTime_WithFormat() throws {
34 | let testFormat = "HH:mm"
35 | let sut = ExampleGenerator.RandomTime(format: testFormat)
36 |
37 | let attributes = try XCTUnwrap(sut.rules)
38 | XCTAssertTrue(attributes.contains { key, _ in
39 | key == "format"
40 | })
41 | XCTAssertEqual(sut.generator, .time)
42 | XCTAssertNotNil(DateHelper.dateFrom(string: try XCTUnwrap(sut.value as? String), format: testFormat))
43 | }
44 |
45 | func testRandomTime_SetsRules() throws {
46 | let testFormat = "HH:mm"
47 | let sut = ExampleGenerator.RandomTime(format: testFormat)
48 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
49 |
50 | XCTAssertEqual(result.format, testFormat)
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/Tests/ExampleGenerators/RandomUuidTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 16/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RandomUUIDTests: XCTestCase {
23 |
24 | func testRandomUUIDExampleGenerator() throws {
25 | let sut = ExampleGenerator.RandomUUID()
26 |
27 | XCTAssertNotNil(UUID(uuidString: try XCTUnwrap(sut.value as? String)))
28 | XCTAssertEqual(sut.generator, .uuid)
29 | XCTAssertNotNil(sut.rules)
30 | }
31 |
32 | func testRandomUUIDDefaultFormat() throws {
33 | let sut = ExampleGenerator.RandomUUID()
34 |
35 | let uuid = try XCTUnwrap(sut.value as? String)
36 | XCTAssertEqual(uuid.count, 36)
37 |
38 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
39 | XCTAssertEqual(result.format, "upper-case-hyphenated")
40 | }
41 |
42 | func testRandomUUIDUpperCaseHyphenatedFormat() throws {
43 | let sut = ExampleGenerator.RandomUUID(format: .uppercaseHyphenated)
44 |
45 | let uuid = try XCTUnwrap(sut.value as? String)
46 | XCTAssertEqual(uuid.count, 36)
47 |
48 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
49 | XCTAssertEqual(result.format, "upper-case-hyphenated")
50 | }
51 |
52 | func testRandomUUIDSimpleFormat() throws {
53 | let sut = ExampleGenerator.RandomUUID(format: .simple)
54 |
55 | let uuid = try XCTUnwrap(sut.value as? String)
56 | XCTAssertEqual(uuid.count, 32)
57 |
58 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
59 | XCTAssertEqual(result.format, "simple")
60 | }
61 |
62 | func testRandomUUIDLowerCaseHyphenatedFormat() throws {
63 | let sut = ExampleGenerator.RandomUUID(format: .lowercaseHyphenated)
64 |
65 | let uuid = try XCTUnwrap(sut.value as? String)
66 | XCTAssertEqual(uuid.count, 36)
67 |
68 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
69 | XCTAssertEqual(result.format, "lower-case-hyphenated")
70 | }
71 |
72 | func testRandomUUIDURNFormat() throws {
73 | let sut = ExampleGenerator.RandomUUID(format: .urn)
74 |
75 | let uuid = try XCTUnwrap(sut.value as? String)
76 | XCTAssertEqual(uuid.prefix(9), "urn:uuid:")
77 |
78 | let result = try ExampleGeneratorTestHelpers.encodeDecode(sut.rules!)
79 | XCTAssertEqual(result.format, "URN")
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/Tests/Extensions/String+PactSwiftTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 7/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class StringExtensionTests: XCTestCase {
23 |
24 | func testConvertsSimpleUUID() {
25 | XCTAssertEqual("1234abcd1234abcf12ababcdef1234567".uuid, UUID(uuidString: "1234abcd-1234-abcf-12ab-abcdef1234567"))
26 | }
27 |
28 | func testInvalidStringUUIDIsNil() {
29 | XCTAssertNil("a".uuid)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/Matchers/DecimalLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class DecimalLikeTests: XCTestCase {
23 |
24 | func testMatcher_DecimalLike_InitsWithValue() throws {
25 | let testResult = try XCTUnwrap((Matcher.DecimalLike(1234).value as Any) as? Decimal)
26 | XCTAssertEqual(testResult, 1234)
27 |
28 | let testDecimalResult = try XCTUnwrap((Matcher.DecimalLike(1234.56).value as Any) as? Decimal)
29 | XCTAssertEqual(testDecimalResult, 1234.56)
30 | }
31 |
32 | func testMatcher_DecimalLike_SetsRules() throws {
33 | let sut = Matcher.DecimalLike(Decimal(1234))
34 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
35 |
36 | XCTAssertEqual(result.first?.match, "decimal")
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Tests/Matchers/EachKeyLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 3/4/2022.
3 | // Copyright © 2022 PACT Foundation. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class EachKeyLikeTests: XCTestCase {
23 |
24 | func testMatcher_EachKeyLike_InitsWithStringValue() throws {
25 | let sut = try XCTUnwrap(Matcher.EachKeyLike("bar").value as? String)
26 | XCTAssertEqual(sut, "bar")
27 | }
28 |
29 | func testMatcher_EachKeyLike_InitsWithIntValue() throws {
30 | let sut = try XCTUnwrap(Matcher.EachKeyLike(123).value as? Int)
31 | XCTAssertEqual(sut, 123)
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Tests/Matchers/EqualToTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 10/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class EqualToTests: XCTestCase {
23 |
24 | func testMatcher_Equal_InitsWithToString() throws {
25 | XCTAssertEqual(try XCTUnwrap(Matcher.EqualTo("TestValue").value as? String), "TestValue")
26 | }
27 |
28 | func testMatcher_Equal_InitsWithToInt() throws {
29 | XCTAssertEqual(try XCTUnwrap(Matcher.EqualTo(32).value as? Int), Int(32))
30 | }
31 |
32 | func testMatcher_EqualTo_InitsWithDouble() throws {
33 | XCTAssertEqual(try XCTUnwrap(Matcher.EqualTo(128.32).value as? Double), Double(128.32))
34 | }
35 |
36 | func testMatcher_EqualTo_InitsWithArrayOfStrings() throws {
37 | XCTAssertEqual(try XCTUnwrap(Matcher.EqualTo(["TestValue", "Teapot"]).value as? [String]), ["TestValue", "Teapot"])
38 | }
39 |
40 | func testMatcher_EqualTo_InitsWithDecimal() throws {
41 | XCTAssertEqual(try XCTUnwrap(Matcher.EqualTo(Decimal(123.45)).value as? Decimal), Decimal(123.45))
42 | }
43 |
44 | func testMatcher_EqualTo_SetsRules() throws {
45 | let sut = Matcher.EqualTo("test")
46 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
47 |
48 | XCTAssertEqual(result.first?.match, "equality")
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/Tests/Matchers/FromProviderStateTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 15/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class FromProviderStateTests: XCTestCase {
23 |
24 | func testMatcher_FromProviderState_InitsWithValue() throws {
25 | let testStringResult = try XCTUnwrap((Matcher.FromProviderState(parameter: "testParameter", value: .string("some-string")).value as Any) as? String)
26 | XCTAssertEqual(testStringResult, "some-string")
27 |
28 | let testIntResult = try XCTUnwrap((Matcher.FromProviderState(parameter: "testParameter", value: .int(100)).value as Any) as? Int)
29 | XCTAssertEqual(testIntResult, 100)
30 |
31 | let testDecimalResult = try XCTUnwrap((Matcher.FromProviderState(parameter: "testParameter", value: .decimal(Decimal(123.45))).value as Any) as? Decimal)
32 | XCTAssertEqual(testDecimalResult, Decimal(123.45))
33 |
34 | let testBoolResult = try XCTUnwrap((Matcher.FromProviderState(parameter: "testParameter", value: .bool(true)).value as Any) as? Bool)
35 | XCTAssertEqual(testBoolResult, true)
36 | }
37 |
38 | func testMatcher_FromProviderState_InitsWithparameter() {
39 | let testParameterResult = Matcher.FromProviderState(parameter: "testParameter", value: .int(100)).parameter
40 | XCTAssertEqual(testParameterResult, "testParameter")
41 | }
42 |
43 | func testMatcher_FromProviderState_SetsRules() throws {
44 | let sut = Matcher.FromProviderState(parameter: "test", value: .string("value"))
45 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
46 |
47 | XCTAssertEqual(result.first?.match, "type")
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Tests/Matchers/IncludesLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 26/5/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class IncludesLikeTests: XCTestCase {
23 |
24 | func testInitsWith_ArrayArgument() throws {
25 | let testResult = Matcher.IncludesLike(["Foo", "Bar"], combine: .AND)
26 |
27 | XCTAssertEqual(testResult.rules.count, 2)
28 | XCTAssertEqual(try XCTUnwrap((testResult.value as Any) as? String), "Foo Bar")
29 | }
30 |
31 | func testInitsWith_VariadicArgument() throws {
32 | let testResult = Matcher.IncludesLike("Foo", "Bar", "Baz", combine: .OR)
33 |
34 | XCTAssertEqual(testResult.rules.count, 3)
35 | XCTAssertEqual(testResult.combine, .OR)
36 | XCTAssertEqual(try XCTUnwrap((testResult.value as Any) as? String), "Foo Bar Baz")
37 | }
38 |
39 | func testInitsWith_ArrayArgument_AndGeneratedValue() throws {
40 | let testResult = Matcher.IncludesLike(["I'm", "Teapot"], combine: .AND, generate: "I'm a little Teapot")
41 |
42 | XCTAssertEqual(testResult.rules.count, 2)
43 | XCTAssertEqual(testResult.combine, .AND)
44 | XCTAssertEqual(try XCTUnwrap((testResult.value as Any) as? String), "I'm a little Teapot")
45 | }
46 |
47 | func testInitsWith_VariadicArgument_AndGeneratedValue() throws {
48 | let testResult = Matcher.IncludesLike("Teapot", "I'm", combine: .AND, generate: "I'm a big Teapot")
49 |
50 | XCTAssertEqual(testResult.rules.count, 2)
51 | XCTAssertEqual(testResult.combine, .AND)
52 | XCTAssertEqual(try XCTUnwrap((testResult.value as Any) as? String), "I'm a big Teapot")
53 | }
54 |
55 | func testMatcher_IncludesLike_SetsRules() throws {
56 | let sut = Matcher.IncludesLike("Teapot", "I'm", combine: .AND, generate: "I'm a big Teapot")
57 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
58 |
59 | XCTAssertTrue(result.allSatisfy { $0.match == "include" })
60 | XCTAssertTrue(result.allSatisfy { encodedModel in
61 | ["Teapot", "I'm"].contains(encodedModel.value)
62 | })
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/Tests/Matchers/IntegerLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class IntegerLikeTests: XCTestCase {
23 |
24 | func testMatcher_IntegerLike_InitsWithValue() throws {
25 | let testResult = try XCTUnwrap((Matcher.IntegerLike(1234).value as Any) as? Int)
26 | XCTAssertEqual(testResult, 1234)
27 | }
28 |
29 | func testMatcher_IntegerLike_SetsRules() throws {
30 | let sut = Matcher.IntegerLike(123)
31 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
32 |
33 | XCTAssertEqual(result.first?.match, "integer")
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Tests/Matchers/MatchNullTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MatchNullTests.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 9/10/20.
6 | // Copyright © 2020 Marko Justinek. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | @testable import PactSwift
12 |
13 | class MatchNullTests: XCTestCase {
14 |
15 | func testMatcher_MatchNull() throws {
16 | let matcherValue = try XCTUnwrap((Matcher.MatchNull().value as Any) as? String)
17 | XCTAssertEqual(matcherValue, "pact_matcher_null")
18 |
19 | let matcherRules = try XCTUnwrap(Matcher.MatchNull().rules.first)
20 | XCTAssertTrue(matcherRules.contains { key, value in
21 | key == "match"
22 | })
23 | }
24 |
25 | func testMatcher_MatchNull_SetsRules() throws {
26 | let sut = Matcher.MatchNull()
27 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
28 |
29 | XCTAssertEqual(result.first?.match, "null")
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/Matchers/RegexLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class RegexLikeTests: XCTestCase {
23 |
24 | func testMatcher_RegexLike_InitsWithValue() throws {
25 | let testResult = try XCTUnwrap(( Matcher.RegexLike(value: "2020-11-04", pattern: "\\d{4}-\\d{2}-\\d{2}").value as Any) as? String)
26 | XCTAssertEqual(testResult, "2020-11-04")
27 | }
28 |
29 | func testMatcher_RegexLike_SetsRules() throws {
30 | let sut = Matcher.RegexLike(value: "2020-11-04", pattern: "\\d{4}-\\d{2}-\\d{2}")
31 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
32 |
33 | XCTAssertEqual(result.first?.match, "regex")
34 | XCTAssertEqual(result.first?.regex, #"\d{4}-\d{2}-\d{2}"#)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Tests/Matchers/SomethingLikeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 11/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class SomethingLikeTests: XCTestCase {
23 |
24 | func testMatcher_SomethingLike_InitsWithValue() throws {
25 | XCTAssertEqual(try XCTUnwrap((Matcher.SomethingLike("TestString").value as Any) as? String), "TestString")
26 | XCTAssertEqual(try XCTUnwrap((Matcher.SomethingLike(200).value as Any) as? Int), 200)
27 | XCTAssertEqual(try XCTUnwrap((Matcher.SomethingLike(123.45).value as Any) as? Double), 123.45)
28 |
29 | let dictResult = try XCTUnwrap((Matcher.SomethingLike(["foo": "bar"]).value as Any) as? [String: String])
30 | XCTAssertEqual(dictResult["foo"], "bar")
31 |
32 | let testArray = [1, 3, 2]
33 | let arrayResult = try XCTUnwrap((Matcher.SomethingLike([1, 2, 3]).value as Any) as? [Int])
34 | XCTAssertEqual(arrayResult.count, 3)
35 | XCTAssertTrue(arrayResult.allSatisfy { testArray.contains($0) })
36 | }
37 |
38 | func testMatcher_SomethingLike_SetsRules() throws {
39 | let sut = Matcher.SomethingLike("test")
40 | let result = try MatcherTestHelpers.encodeDecode(sut.rules)
41 |
42 | XCTAssertEqual(result.first?.match, "type")
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/Tests/Model/InteractionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 26/5/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class InteractionTests: XCTestCase {
23 |
24 | var sut: Interaction!
25 |
26 | func testConvenienceInit_WithDescription() {
27 | sut = Interaction(description: "A test request")
28 | XCTAssertEqual(sut.interactionDescription, "A test request")
29 | }
30 |
31 | func testGivenState_WithArray() {
32 | sut = Interaction(description: "A test request with array of states")
33 | let providerState = ProviderState(description: "array exists", params: ["foo": "bar"])
34 | let sutWithInteraction = sut.given([providerState])
35 |
36 | XCTAssertEqual(sutWithInteraction.providerStates, [providerState])
37 | XCTAssertEqual(sutWithInteraction.providerStates?.count, 1)
38 | }
39 |
40 | func testGivenState_WithVariadicParameter() throws {
41 | sut = Interaction(description: "A test request with states as variadic param")
42 | let oneProviderState = ProviderState(description: "array exists", params: ["foo": "bar"])
43 | let twoProviderState = ProviderState(description: "variadic exists", params: ["bar": "baz"])
44 | let sutWithInteraction = sut.given(oneProviderState, twoProviderState)
45 |
46 | let providerStates = try XCTUnwrap(sutWithInteraction.providerStates)
47 | XCTAssertEqual(providerStates.count, 2)
48 | XCTAssertTrue(providerStates.contains(oneProviderState))
49 | XCTAssertTrue(providerStates.contains(twoProviderState))
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Tests/Model/MetadataTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 1/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class MetadataTests: XCTestCase {
23 |
24 | func testMetadata_SetsPactSpecificationVersion() {
25 | XCTAssertEqual(Metadata().pactSpec.version, "3.0.0")
26 | }
27 |
28 | #if !SWIFT_PACKAGE
29 | func testMetadata_SetsPactSwiftVersion() throws {
30 | guard let expectedResult = bundleVersion() else {
31 | XCTFail("Expected version number")
32 | return
33 | }
34 | XCTAssertEqual(try XCTUnwrap(Metadata().pactSwift.version), expectedResult)
35 | }
36 | #endif
37 |
38 | }
39 |
40 | private extension MetadataTests {
41 |
42 | func bundleVersion() -> String? {
43 | #if os(iOS)
44 | return Bundle(identifier: "au.com.pact-foundation.iOS.PactSwift")?.infoDictionary?["CFBundleShortVersionString"] as? String
45 | #elseif os(macOS)
46 | return Bundle(identifier: "au.com.pact-foundation.macOS.PactSwift")?.infoDictionary?["CFBundleShortVersionString"] as? String ?? pactSwiftVersion
47 | #else
48 | return nil
49 | #endif
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/Tests/Model/PactHTTPMethodTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 29/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 | @testable import PactSwift
20 |
21 | final class PactHTTPMehtodTests: XCTestCase {
22 |
23 | func testPactHTTPMethods() {
24 | XCTAssertEqual(PactHTTPMethod.GET.method, "get")
25 | XCTAssertEqual(PactHTTPMethod.HEAD.method, "head")
26 | XCTAssertEqual(PactHTTPMethod.POST.method, "post")
27 | XCTAssertEqual(PactHTTPMethod.PUT.method, "put")
28 | XCTAssertEqual(PactHTTPMethod.PATCH.method, "patch")
29 | XCTAssertEqual(PactHTTPMethod.DELETE.method, "delete")
30 | XCTAssertEqual(PactHTTPMethod.TRACE.method, "trace")
31 | XCTAssertEqual(PactHTTPMethod.CONNECT.method, "connect")
32 | XCTAssertEqual(PactHTTPMethod.OPTIONS.method, "options")
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/Model/PacticipantTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 1/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | class PacticipantTests: XCTestCase {
23 |
24 | func testPacticipant_ReturnsConsumerName() {
25 | XCTAssertEqual(Pacticipant.consumer("test_consumer").name, "test_consumer")
26 | }
27 |
28 | func testPacticipant_ReturnsProviderName() {
29 | XCTAssertEqual(Pacticipant.provider("test_provider").name, "test_provider")
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/Model/ToolboxTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToolboxTests.swift
3 | // PactSwift
4 | //
5 | // Created by Marko Justinek on 27/10/20.
6 | // Copyright © 2020 Marko Justinek. 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 XCTest
22 |
23 | @testable import PactSwift
24 |
25 | class ToolboxTests: XCTestCase {
26 |
27 | func testMerge_ReturnsNil() {
28 | let testSubject = Toolbox.merge(body: nil, query: nil, header: nil, path: nil)
29 |
30 | XCTAssertNil(testSubject)
31 | }
32 |
33 | func testMerge_HandlesArguments() throws {
34 | let testBody = AnyEncodable("foo:body")
35 | let testQuery = AnyEncodable("foo:query")
36 | let testHeader = AnyEncodable("foo:header")
37 |
38 | let testSubject = Toolbox.merge(body: testBody, query: testQuery, header: testHeader, path: nil)
39 | let mergedObjectKeys = try XCTUnwrap(processAnyEncodable(object: testSubject as Any))
40 |
41 | let expectedObjectKeys = ["body", "query", "header"]
42 | XCTAssertTrue(
43 | expectedObjectKeys.allSatisfy { value in
44 | mergedObjectKeys.contains(value)
45 | }
46 | )
47 | }
48 |
49 | func testProcess_Throws_NonEncodable() {
50 | struct NonSupportedType {
51 | let some = "Uh oh!"
52 | }
53 | let nonSupportedType = NonSupportedType()
54 |
55 | do {
56 | _ = try Toolbox.process(element: nonSupportedType, for: .body)
57 | XCTFail("Should fail with EncodingError")
58 | } catch {
59 | XCTAssertTrue((error as Any) is EncodingError)
60 | }
61 | }
62 |
63 | }
64 |
65 | private extension ToolboxTests {
66 |
67 | func processAnyEncodable(object: Any) -> [String]? {
68 | switch object {
69 | case let dict as [String: Any]:
70 | var mergedKeys: [String] = []
71 | for key in dict.keys {
72 | mergedKeys.append(key)
73 | }
74 | return mergedKeys
75 | default:
76 | XCTFail("Should only expect a Dictionary here as Toolbox.merge() should return it")
77 | return nil
78 | }
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/Tests/Model/TransferProtocolTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 7/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | #if compiler(>=5.5)
23 | @_implementationOnly import PactSwiftMockServer
24 | #else
25 | import PactSwiftMockServer
26 | #endif
27 |
28 | class TransferProtocolTests: XCTestCase {
29 |
30 | func testTransferProtocol() {
31 | XCTAssertEqual(TransferProtocol.standard.protocol, "http")
32 | XCTAssertEqual(TransferProtocol.secure.protocol, "https")
33 | }
34 |
35 | func testTransferProtocolBridge() {
36 | XCTAssertEqual(TransferProtocol.standard.bridge, PactSwiftMockServer.TransferProtocol.standard)
37 | XCTAssertEqual(TransferProtocol.secure.bridge, PactSwiftMockServer.TransferProtocol.secure)
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/Tests/Model/VersionSelectorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 28/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import PactSwift
21 |
22 | final class VersionSelectorTests: XCTestCase {
23 |
24 | func testVersionSelectorInitializes() {
25 | let testSubject = VersionSelector(tag: "test-tag")
26 |
27 | XCTAssertEqual(testSubject.tag, "test-tag")
28 | XCTAssertNil(testSubject.fallbackTag)
29 | XCTAssertTrue(testSubject.latest)
30 | XCTAssertNil(testSubject.consumer)
31 | }
32 |
33 | func testVersionSelectorSetsFallbackTag() {
34 | let testSubject = VersionSelector(tag: "test-tag", fallbackTag: "fallback-tag")
35 |
36 | XCTAssertEqual(testSubject.tag, "test-tag")
37 | XCTAssertEqual(testSubject.fallbackTag, "fallback-tag")
38 | }
39 |
40 | func testVersionSelectorSetsLatest() {
41 | let testSubject = VersionSelector(tag: "test-tag", latest: false)
42 |
43 | XCTAssertFalse(testSubject.latest)
44 | }
45 |
46 | func testVersionSelectorSetsConsumer() {
47 | let testSubject = VersionSelector(tag: "test-tag", consumer: "api-consumer")
48 |
49 | XCTAssertEqual(testSubject.consumer, "api-consumer")
50 | }
51 |
52 | func testVersionSelectorJSONString() throws {
53 | let testSubject = try VersionSelector(tag: "test", fallbackTag: "main", latest: true, consumer: "api-consumer").toJSONString()
54 |
55 | XCTAssertTrue(testSubject.contains("\"tag\":\"test\""))
56 | XCTAssertTrue(testSubject.contains("\"fallbackTag\":\"main\""))
57 | XCTAssertTrue(testSubject.contains("\"latest\":true"))
58 | XCTAssertTrue(testSubject.contains("\"consumer\":\"api-consumer\""))
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/Tests/Model/WIPPactsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 28/8/21.
3 | // Copyright © 2021 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 | import XCTest
18 |
19 | @testable import PactSwift
20 |
21 | final class WIPPactsTests: XCTestCase {
22 |
23 | func testWIPPactsInitializesWithDate() {
24 | let testDate = Date()
25 | let testSubject = WIPPacts(since: testDate, providerVersion: "test")
26 |
27 | XCTAssertEqual(testSubject.sinceDate, testDate)
28 | }
29 |
30 | func testWIPPactsInitializesWithProviderVersion() {
31 | let testSubject = WIPPacts(since: Date(), providerVersion: "test")
32 |
33 | XCTAssertEqual(testSubject.providerVersion, "test")
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Tests/TestHelpers/DateHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 17/9/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | enum DateHelper {
21 |
22 | static func dateFrom(isoString: String, isoFormat: ISO8601DateFormatter.Options) -> Date? {
23 | let formatter = ISO8601DateFormatter()
24 | formatter.formatOptions = isoFormat
25 | return formatter.date(from: isoString)
26 | }
27 |
28 | static func dateFrom(string: String, format: String) -> Date? {
29 | let formatter = DateFormatter()
30 | formatter.dateFormat = format
31 | return formatter.date(from: string)
32 | }
33 |
34 | static func stringFrom(date: Date, format: String) -> String {
35 | let formatter = DateFormatter()
36 | formatter.dateFormat = format
37 | return formatter.string(from: date)
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/Tests/TestHelpers/ErrorCapture.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 20/4/20.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 |
20 | @testable import PactSwift
21 |
22 | struct ErrorReceived {
23 |
24 | var message: String
25 | var file: FileString?
26 | var line: UInt?
27 |
28 | }
29 |
30 | class ErrorCapture: ErrorReportable {
31 |
32 | public var error: ErrorReceived?
33 |
34 | func reportFailure(_ message: String) {
35 | self.error = ErrorReceived(message: message, file: nil, line: nil)
36 | }
37 |
38 | func reportFailure(_ message: String, file: FileString, line: UInt) {
39 | self.error = ErrorReceived(message: message, file: file, line: line)
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Tests/TestHelpers/ExampleGeneratorTestHelpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 25/10/21.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 | @testable import PactSwift
20 |
21 | enum ExampleGeneratorTestHelpers {
22 |
23 | /// Encodes a model containing `AnyEncodable` type and decodes the value into String? or Int? type
24 | static func encodeDecode(_ model: [String: AnyEncodable]) throws -> DecodableTypeModel {
25 | let data = try JSONEncoder().encode(EncodableModel(params: model).params)
26 | return try JSONDecoder().decode(DecodableTypeModel.self, from: data)
27 | }
28 |
29 | struct EncodableModel: Encodable {
30 | let params: [String: AnyEncodable]
31 | }
32 |
33 | struct DecodableTypeModel: Decodable {
34 | let expression: String?
35 | let digits: Int?
36 | let format: String?
37 | let max: Int?
38 | let min: Int?
39 | let regex: String?
40 | let size: Int?
41 | let type: String?
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/TestHelpers/MatcherTestHelpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Marko Justinek on 25/10/21.
3 | // Copyright © 2020 Marko Justinek. All rights reserved.
4 | //
5 | // Permission to use, copy, modify, and/or distribute this software for any
6 | // purpose with or without fee is hereby granted, provided that the above
7 | // copyright notice and this permission notice appear in all copies.
8 | //
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 | // IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 | //
17 |
18 | import Foundation
19 | @testable import PactSwift
20 |
21 | enum MatcherTestHelpers {
22 |
23 | /// Encodes a model containing `AnyEncodable` type and decodes the value into String type
24 | static func encodeDecode(_ model: [[String: AnyEncodable]]) throws -> [DecodableModel] {
25 | let data = try JSONEncoder().encode(EncodableModel(params: model).params)
26 | return try JSONDecoder().decode([DecodableModel].self, from: data)
27 | }
28 |
29 | struct EncodableModel: Encodable {
30 | let params: [[String: AnyEncodable]]
31 | }
32 |
33 | struct DecodableModel: Decodable {
34 | let match: String
35 | let min: Int?
36 | let max: Int?
37 | let regex: String?
38 | let value: String?
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | require_ci_to_pass: yes
4 |
5 | coverage:
6 | precision: 2
7 | round: down
8 | range: "75...100"
9 |
10 | status:
11 | project: yes
12 | patch: yes
13 | changes: no
14 |
15 | ignore:
16 | - "Tests/**/*"
17 | - "Tests"
18 |
19 | parsers:
20 | gcov:
21 | branch_detection:
22 | conditional: yes
23 | loop: yes
24 | method: no
25 | macro: no
26 |
27 | comment:
28 | layout: "header, diff"
29 | behavior: default
30 | require_changes: no
31 |
--------------------------------------------------------------------------------