Skip to content

Commit

Permalink
Fix the Codable conformances on Expandable to be compliant (fixes sev…
Browse files Browse the repository at this point in the history
…eral issues), fix the KeyedDecodingContainer override to specifically handle Expandable (fixes the missing "transfer" key issue), make the test show errors better. Oh, and some much better CI.
  • Loading branch information
gwynne committed Sep 23, 2021
1 parent 668b83c commit b36e0f8
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 54 deletions.
57 changes: 45 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,54 @@
name: 'Test'

on:
push: { branches: [ main ] }
pull_request:
types: [opened]
branches:
- 'master'

jobs:
test:
name: Running Tests
linux:
strategy:
fail-fast: false
matrix:
swiftver:
- 'swift:5.2'
- 'swift:5.3'
- 'swift:5.4'
- 'swift:5.5'
- 'swiftlang/swift:nightly-main'
swiftos:
- bionic
- focal
- centos7
- centos8
- amazonlinux2
container: ${{ format('{0}-{1}', matrix.swiftver, matrix.swiftos) }}
runs-on: ubuntu-latest

steps:
- name: 'Checking out repo'
uses: actions/checkout@v2

- name: 'Running Tests'
run: swift test --enable-test-discovery

- name: Workaround SPM incompatibility with old Git on CentOS 7
if: ${{ contains(matrix.swiftos, 'centos7') }}
run: |
yum install -y make libcurl-devel
git clone https://github.com/git/git -bv2.28.0 --depth 1 && cd git
make prefix=/usr -j all install NO_OPENSSL=1 NO_EXPAT=1 NO_TCLTK=1 NO_GETTEXT=1 NO_PERL=1
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with Thread Sanitizer
run: swift test --enable-test-discovery --sanitize=thread

macos:
strategy:
fail-fast: false
matrix:
xcode:
- latest-stable
- latest
runs-on: macos-latest
steps:
- name: Select latest available Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ matrix.xcode }}
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests with Thread Sanitizer
run: swift test --enable-test-discovery --sanitize=thread
31 changes: 22 additions & 9 deletions Sources/StripeKit/Shared Models/StripeExpandable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import Foundation

extension KeyedDecodingContainer {
func decode<T>(_ type: T.Type, forKey key: Self.Key) throws -> T where T : Decodable {
return try decodeIfPresent(type, forKey: key) ?? T(from: self.superDecoder(forKey: key))
public func decode<U>(_ type: Expandable<U>.Type, forKey key: Self.Key) throws -> Expandable<U> where U: StripeModel {
return try decodeIfPresent(type, forKey: key) ?? Expandable<U>()
}
}

Expand All @@ -22,26 +22,39 @@ public class Expandable<Model: StripeModel>: StripeModel {
case empty
}

required public init() {
self._state = .empty
}

required public init(from decoder: Decoder) throws {
let codingPath = decoder.codingPath
do {
_state = try .unexpanded(String(from: decoder))
} catch DecodingError.typeMismatch(_, _) {
_state = try .expanded(Model(from: decoder))
} catch {
let container = try decoder.singleValueContainer()
do {
if container.decodeNil() {
_state = .empty
} else {
_state = .unexpanded(try container.decode(String.self))
}
} catch DecodingError.typeMismatch(let type, _) where type is String.Type {
_state = .expanded(try container.decode(Model.self))
}
} catch DecodingError.keyNotFound(_, let context) where context.codingPath.count == codingPath.count {
_state = .empty
}
}

private var _state: ExpandableState

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

switch _state {
case let .unexpanded(id):
try id.encode(to: encoder)
try container.encode(id)
case let .expanded(model):
try model.encode(to: encoder)
try container.encode(model)
default:
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
Expand Down
61 changes: 28 additions & 33 deletions Tests/StripeKitTests/ExpandableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,42 +322,37 @@ class ExpandableTests: XCTestCase {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
_ = try decoder.decode(StripeEventData.self, from: objectMissingExpandableTransferFieldOnCharge)
} catch {
XCTFail(error.localizedDescription)
}
_ = try decoder.decode(StripeEventData.self, from: objectMissingExpandableTransferFieldOnCharge)
}

func testExpandable_nullEncodingDecoding() throws {
let session =
"""
{
"amountTotal": 100,
"id": "cs_test_ffff",
"successUrl": "https://example.com",
"livemode": false,
"customer": null,
"metadata": {},
"totalDetails": {
"amountShipping": 0,
"amountTax": 0,
"amountDiscount": 0
},
"setupIntent": null,
"object": "checkout.session",
"mode": "payment",
"amountSubtotal": 100,
"paymentIntent": "pi_ffff",
"paymentMethodTypes": [
"card"
],
"cancelUrl": "https://example.com",
"subscription": null,
"currency": "usd",
"paymentStatus": "unpaid"
}
""".data(using: .utf8)!
let session = """
{
"amountTotal": 100,
"id": "cs_test_ffff",
"successUrl": "https://example.com",
"livemode": false,
"customer": null,
"metadata": {},
"totalDetails": {
"amountShipping": 0,
"amountTax": 0,
"amountDiscount": 0
},
"setupIntent": null,
"object": "checkout.session",
"mode": "payment",
"amountSubtotal": 100,
"paymentIntent": "pi_ffff",
"paymentMethodTypes": [
"card"
],
"cancelUrl": "https://example.com",
"subscription": null,
"currency": "usd",
"paymentStatus": "unpaid"
}
""".data(using: .utf8)!
let sess = try JSONDecoder().decode(StripeSession.self, from: session)
_ = try JSONDecoder().decode(StripeSession.self, from: JSONEncoder().encode(sess))
}
Expand Down

0 comments on commit b36e0f8

Please sign in to comment.