Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure currency formatting matches expected currency formatting #120

Merged
merged 7 commits into from
Oct 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Afterpay.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
15F7DDB725393BD30011EC25 /* CurrencyFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F7DDB625393BD30011EC25 /* CurrencyFormatter.swift */; };
6602EF0F25358A8000A0468C /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6602EF0E25358A8000A0468C /* ColorScheme.swift */; };
6605666324E5199500DA588E /* Locales.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6605666224E5199500DA588E /* Locales.swift */; };
6615F99B24D14620005036F1 /* SVG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6615F99A24D14620005036F1 /* SVG.swift */; };
Expand All @@ -21,8 +22,8 @@
6672982A25357D80001D1C5A /* SVGConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6672982925357D80001D1C5A /* SVGConfiguration.swift */; };
667AD3542497121200BF94E5 /* CheckoutWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 667AD3532497121100BF94E5 /* CheckoutWebViewController.swift */; };
6689536C24C96CB5005090B4 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6689536B24C96CB5005090B4 /* Configuration.swift */; };
66C3F7FB25397A810086DD0A /* CurrencyFormatterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C3F7FA25397A810086DD0A /* CurrencyFormatterTests.swift */; };
66D685B224BD3FB900C7287C /* SwiftUIWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66D685B124BD3FB900C7287C /* SwiftUIWrapper.swift */; };
66DAAC8924E0CE7700127460 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66DAAC8824E0CE7700127460 /* Currency.swift */; };
66DAAC8B24E0CF0100127460 /* PriceBreakdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66DAAC8A24E0CF0100127460 /* PriceBreakdown.swift */; };
66DAAC8D24E109D200127460 /* PriceBreakdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66DAAC8C24E109D200127460 /* PriceBreakdownTests.swift */; };
66E255AE24E3C14600C81F20 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E255AD24E3C14600C81F20 /* Strings.swift */; };
Expand All @@ -43,6 +44,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
15F7DDB625393BD30011EC25 /* CurrencyFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyFormatter.swift; sourceTree = "<group>"; };
6602EF0E25358A8000A0468C /* ColorScheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = "<group>"; };
6605666224E5199500DA588E /* Locales.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locales.swift; sourceTree = "<group>"; };
6615F99A24D14620005036F1 /* SVG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SVG.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -70,8 +72,8 @@
66B57E55248F5C7D0020C642 /* Project-Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Project-Shared.xcconfig"; sourceTree = "<group>"; };
66B57E56248F5C7D0020C642 /* Project-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Project-Release.xcconfig"; sourceTree = "<group>"; };
66B57E57248F5C7D0020C642 /* Afterpay-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Afterpay-Release.xcconfig"; sourceTree = "<group>"; };
66C3F7FA25397A810086DD0A /* CurrencyFormatterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyFormatterTests.swift; sourceTree = "<group>"; };
66D685B124BD3FB900C7287C /* SwiftUIWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIWrapper.swift; sourceTree = "<group>"; };
66DAAC8824E0CE7700127460 /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = "<group>"; };
66DAAC8A24E0CF0100127460 /* PriceBreakdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceBreakdown.swift; sourceTree = "<group>"; };
66DAAC8C24E109D200127460 /* PriceBreakdownTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceBreakdownTests.swift; sourceTree = "<group>"; };
66E255AD24E3C14600C81F20 /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -142,6 +144,7 @@
isa = PBXGroup;
children = (
6635B95E24CAA9F000EBB3A6 /* ConfigurationTests.swift */,
66C3F7FA25397A810086DD0A /* CurrencyFormatterTests.swift */,
665FC57B2488766C00A5A93E /* Info.plist */,
66DAAC8C24E109D200127460 /* PriceBreakdownTests.swift */,
);
Expand Down Expand Up @@ -209,7 +212,7 @@
isa = PBXGroup;
children = (
6689536B24C96CB5005090B4 /* Configuration.swift */,
66DAAC8824E0CE7700127460 /* Currency.swift */,
15F7DDB625393BD30011EC25 /* CurrencyFormatter.swift */,
6605666224E5199500DA588E /* Locales.swift */,
66DAAC8A24E0CF0100127460 /* PriceBreakdown.swift */,
);
Expand Down Expand Up @@ -418,6 +421,7 @@
files = (
6635B95F24CAA9F000EBB3A6 /* ConfigurationTests.swift in Sources */,
66DAAC8D24E109D200127460 /* PriceBreakdownTests.swift in Sources */,
66C3F7FB25397A810086DD0A /* CurrencyFormatterTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -432,6 +436,7 @@
6602EF0F25358A8000A0468C /* ColorScheme.swift in Sources */,
6672982A25357D80001D1C5A /* SVGConfiguration.swift in Sources */,
6689536C24C96CB5005090B4 /* Configuration.swift in Sources */,
15F7DDB725393BD30011EC25 /* CurrencyFormatter.swift in Sources */,
66DAAC8B24E0CF0100127460 /* PriceBreakdown.swift in Sources */,
662A3AED24A999A500EFD826 /* CheckoutResult.swift in Sources */,
667AD3542497121200BF94E5 /* CheckoutWebViewController.swift in Sources */,
Expand All @@ -440,7 +445,6 @@
66D685B224BD3FB900C7287C /* SwiftUIWrapper.swift in Sources */,
666D334C24A48F5C00FCD464 /* ObjcWrapper.swift in Sources */,
946388FE24DD077F00A1227A /* InfoWebViewController.swift in Sources */,
66DAAC8924E0CE7700127460 /* Currency.swift in Sources */,
66EE9BD724DCEC3E00A81C19 /* LinkTextView.swift in Sources */,
6605666324E5199500DA588E /* Locales.swift in Sources */,
);
Expand Down
104 changes: 104 additions & 0 deletions AfterpayTests/CurrencyFormatterTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// CurrencyFormatterTests.swift
// AfterpayTests
//
// Created by Adam Campbell on 16/10/20.
// Copyright © 2020 Afterpay. All rights reserved.
//

@testable import Afterpay
import XCTest

class CurrencyFormatterTests: XCTestCase {

func testAustraliaLocale() {
let formatter: (String?) -> CurrencyFormatter = { currencyCode in
CurrencyFormatter(locale: Locales.australia, currencyCode: currencyCode!)
}

let audFormatter = formatter(Locales.australia.currencyCode)
let cadFormatter = formatter(Locales.canada.currencyCode)
let gbpFormatter = formatter(Locales.greatBritain.currencyCode)
let nzdFormatter = formatter(Locales.newZealand.currencyCode)
let usdFormatter = formatter(Locales.unitedStates.currencyCode)

XCTAssertEqual(audFormatter.string(from: 120), "$120.00")
XCTAssertEqual(cadFormatter.string(from: 120), "$120.00 CAD")
XCTAssertEqual(gbpFormatter.string(from: 120), "£120.00")
XCTAssertEqual(nzdFormatter.string(from: 120), "$120.00 NZD")
XCTAssertEqual(usdFormatter.string(from: 120), "$120.00 USD")
}

func testCanadaLocale() {
let formatter: (String?) -> CurrencyFormatter = { currencyCode in
CurrencyFormatter(locale: Locales.canada, currencyCode: currencyCode!)
}

let audFormatter = formatter(Locales.australia.currencyCode)
let cadFormatter = formatter(Locales.canada.currencyCode)
let gbpFormatter = formatter(Locales.greatBritain.currencyCode)
let nzdFormatter = formatter(Locales.newZealand.currencyCode)
let usdFormatter = formatter(Locales.unitedStates.currencyCode)

XCTAssertEqual(audFormatter.string(from: 120), "$120.00 AUD")
XCTAssertEqual(cadFormatter.string(from: 120), "$120.00")
XCTAssertEqual(gbpFormatter.string(from: 120), "£120.00")
XCTAssertEqual(nzdFormatter.string(from: 120), "$120.00 NZD")
XCTAssertEqual(usdFormatter.string(from: 120), "$120.00 USD")
}

func testGreatBritainLocale() {
let formatter: (String?) -> CurrencyFormatter = { currencyCode in
CurrencyFormatter(locale: Locales.greatBritain, currencyCode: currencyCode!)
}

let audFormatter = formatter(Locales.australia.currencyCode)
let cadFormatter = formatter(Locales.canada.currencyCode)
let gbpFormatter = formatter(Locales.greatBritain.currencyCode)
let nzdFormatter = formatter(Locales.newZealand.currencyCode)
let usdFormatter = formatter(Locales.unitedStates.currencyCode)

XCTAssertEqual(audFormatter.string(from: 120), "$120.00 AUD")
XCTAssertEqual(cadFormatter.string(from: 120), "$120.00 CAD")
XCTAssertEqual(gbpFormatter.string(from: 120), "£120.00")
XCTAssertEqual(nzdFormatter.string(from: 120), "$120.00 NZD")
XCTAssertEqual(usdFormatter.string(from: 120), "$120.00 USD")
}

func testNewZealandLocale() {
let formatter: (String?) -> CurrencyFormatter = { currencyCode in
CurrencyFormatter(locale: Locales.newZealand, currencyCode: currencyCode!)
}

let audFormatter = formatter(Locales.australia.currencyCode)
let cadFormatter = formatter(Locales.canada.currencyCode)
let gbpFormatter = formatter(Locales.greatBritain.currencyCode)
let nzdFormatter = formatter(Locales.newZealand.currencyCode)
let usdFormatter = formatter(Locales.unitedStates.currencyCode)

XCTAssertEqual(audFormatter.string(from: 120), "$120.00 AUD")
XCTAssertEqual(cadFormatter.string(from: 120), "$120.00 CAD")
XCTAssertEqual(gbpFormatter.string(from: 120), "£120.00")
XCTAssertEqual(nzdFormatter.string(from: 120), "$120.00")
XCTAssertEqual(usdFormatter.string(from: 120), "$120.00 USD")
}

func testUnitedStatesLocale() {
let formatter: (String?) -> CurrencyFormatter = { currencyCode in
CurrencyFormatter(locale: Locales.unitedStates, currencyCode: currencyCode!)
}

let audFormatter = formatter(Locales.australia.currencyCode)
let cadFormatter = formatter(Locales.canada.currencyCode)
let gbpFormatter = formatter(Locales.greatBritain.currencyCode)
let nzdFormatter = formatter(Locales.newZealand.currencyCode)
let usdFormatter = formatter(Locales.unitedStates.currencyCode)

XCTAssertEqual(audFormatter.string(from: 120), "A$120.00")
XCTAssertEqual(cadFormatter.string(from: 120), "CA$120.00")
XCTAssertEqual(gbpFormatter.string(from: 120), "£120.00")
XCTAssertEqual(nzdFormatter.string(from: 120), "NZ$120.00")
XCTAssertEqual(usdFormatter.string(from: 120), "$120.00")
}

}
10 changes: 5 additions & 5 deletions Sources/Afterpay/Model/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public struct Configuration {

let minimumAmount: Decimal?
let maximumAmount: Decimal
let currency: Currency
let currencyCode: String
let locale: Locale

/// Creates a new configuration by taking in a minimum and maximum amount as well as a currency
Expand Down Expand Up @@ -71,8 +71,8 @@ public struct Configuration {
/// rounded to 2 decimal places. However values convertible to a Swift Decimal are accepted.
/// - maximumAmount: A amount string representation of a decimal number, rounded to 2
/// decimal places. However values convertible to a Swift Decimal are accepted.
/// - currencyCode: The currency in ISO 4217 format. Supported values include "AUD", "NZD",
/// "USD", and "CAD". However values recognized by Foundation are accepted.
/// - currencyCode: The currency in ISO 4217 format. Supported values include "AUD", "CAD",
/// "GBP", "NZD" and "USD".
/// - locale: The locale required for display of the appropriate terms and conditions and used
/// for formatting of currency. For example if the locale is set to en_AU are specified as USD.
/// More examples are available in the currency tab of the js sandbox:
Expand Down Expand Up @@ -101,7 +101,7 @@ public struct Configuration {
throw ConfigurationError.invalidOrdering(minimum: minimumAmount!, maximum: maximumAmount)
}

guard let currency = Currency(currencyCode: currencyCode) else {
guard Locales.validSet.map(\.currencyCode).contains(currencyCode) else {
throw ConfigurationError.invalidCurrencyCode(currencyCode)
}

Expand All @@ -111,7 +111,7 @@ public struct Configuration {

self.minimumAmount = minimumDecimal
self.maximumAmount = maximumDecimal
self.currency = currency
self.currencyCode = currencyCode
self.locale = locale
}

Expand Down
53 changes: 0 additions & 53 deletions Sources/Afterpay/Model/Currency.swift

This file was deleted.

38 changes: 38 additions & 0 deletions Sources/Afterpay/Model/CurrencyFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// CurrencyFormatter.swift
// Afterpay
//
// Created by Adam Campbell on 16/10/20.
// Copyright © 2020 Afterpay. All rights reserved.
//

import Foundation

private let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()

struct CurrencyFormatter {

let locale: Locale
let currencyCode: String

func string(from decimal: Decimal) -> String? {
if locale == Locales.unitedStates || locale.currencyCode == currencyCode {
formatter.locale = locale
formatter.currencyCode = currencyCode
return formatter.string(from: decimal as NSDecimalNumber)
} else {
let currencyLocale = Locales.validSet.first { $0.currencyCode == currencyCode }
formatter.locale = currencyLocale
formatter.currencyCode = currencyCode
let formattedString = formatter.string(from: decimal as NSDecimalNumber)
return currencyLocale?.currencySymbol == Locales.unitedStates.currencySymbol
? formattedString?.appending(" \(currencyCode)")
: formattedString
}
}

}
12 changes: 3 additions & 9 deletions Sources/Afterpay/Model/PriceBreakdown.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@

import Foundation

private let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()

struct PriceBreakdown {

enum BadgePlacement: Equatable {
Expand All @@ -26,10 +20,10 @@ struct PriceBreakdown {

init(totalAmount: Decimal) {
let configuration = getConfiguration()
let formatter = configuration
.map { CurrencyFormatter(locale: $0.locale, currencyCode: $0.currencyCode) }
let format = { formatter?.string(from: $0) }

formatter.currencySymbol = configuration?.currency.symbol

let format: (Decimal) -> String? = { formatter.string(from: $0 as NSDecimalNumber) }
let formattedMinimum = configuration?.minimumAmount.flatMap(format)
let formattedMaximum = (configuration?.maximumAmount).flatMap(format)
let formattedPayment = format(totalAmount / 4)
Expand Down
8 changes: 2 additions & 6 deletions Sources/Afterpay/Views/SVGView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,13 @@ import UIKit

final class SVGView: Macaw.SVGView {

var svg: SVG {
svgConfiguration.svg(localizedFor: locale, withTraits: traitCollection)
}
var svg: SVG { svgConfiguration.svg(localizedFor: locale, withTraits: traitCollection) }

var svgConfiguration: SVGConfiguration {
didSet { svgDidChange() }
}

private var locale: Locale {
getConfiguration()?.locale ?? Locales.unitedStates
}
private var locale: Locale { getConfiguration()?.locale ?? Locales.unitedStates }

init(svgConfiguration: SVGConfiguration) {
self.svgConfiguration = svgConfiguration
Expand Down