Skip to content

Commit 0217fed

Browse files
Adds basic implementation of Consolidatable for reuse in other projects
1 parent 5b251f2 commit 0217fed

6 files changed

Lines changed: 165 additions & 3 deletions

File tree

.gitignore

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ playground.xcworkspace
3535
# Swift Package Manager
3636
#
3737
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38-
# Packages/
39-
# Package.pins
40-
# Package.resolved
38+
Packages/
39+
Package.pins
40+
Package.resolved
4141
.build/
42+
.DS_Store
43+
/*.xcodeproj
44+
.swiftpm
4245

4346
# CocoaPods
4447
#

Package.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// swift-tools-version:5.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "Consolidate",
8+
products: [
9+
.library(
10+
name: "Consolidate",
11+
type: .static,
12+
targets: ["Consolidate"]),
13+
],
14+
dependencies: [],
15+
targets: [
16+
.target(
17+
name: "Consolidate",
18+
dependencies: []),
19+
.testTarget(
20+
name: "ConsolidateTests",
21+
dependencies: ["Consolidate"]),
22+
]
23+
)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Consolidatable.swift
3+
// Consolidate
4+
//
5+
// Created by Chris Hargreaves on 28/09/2019.
6+
// Copyright © 2019 Software Engineering Limited. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
protocol Consolidatable {
12+
13+
var consolidationGroup: AnyHashable { get }
14+
15+
func consolidate(with other: Self) -> Self
16+
17+
}
18+
19+
extension Array where Element: Consolidatable {
20+
21+
func consolidated() -> Self {
22+
23+
return reduce([]) { (result, element) -> [Element] in
24+
25+
if let existingGroupIndex = result.firstIndex(where: { $0.consolidationGroup == element.consolidationGroup }) {
26+
27+
var mutableResult = result
28+
29+
mutableResult[existingGroupIndex] = result[existingGroupIndex].consolidate(with: element)
30+
31+
return mutableResult
32+
}
33+
34+
return result + [element]
35+
}
36+
}
37+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//
2+
// ConsolidatableTests.swift
3+
// Consolidate
4+
//
5+
// Created by Chris Hargreaves on 28/09/2019.
6+
// Copyright © 2019 Software Engineering Limited. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import Consolidate
11+
12+
final class ConsolidatableTests: XCTestCase {
13+
14+
func test_emptyArray_returnsEmptyArray() {
15+
16+
let consolidatedTaxes: [TaxAmount] = [].consolidated()
17+
18+
XCTAssertEqual(consolidatedTaxes, [])
19+
}
20+
21+
func test_noConsolidabaleValues_doesNotConsolidate() {
22+
23+
let importTax = TaxAmount(tax: "Import Tax", amount: 3.00)
24+
let salesTax = TaxAmount(tax: "Sales Tax", amount: 1.75)
25+
let exportTax = TaxAmount(tax: "Export Tax", amount: 2.30)
26+
let incomeTax = TaxAmount(tax: "Income Tax", amount: 2.35)
27+
28+
let consolidatedTaxes = [
29+
importTax,
30+
salesTax,
31+
exportTax,
32+
incomeTax
33+
].consolidated()
34+
35+
XCTAssertEqual(consolidatedTaxes, [
36+
TaxAmount(tax: "Import Tax", amount: 3.00),
37+
TaxAmount(tax: "Sales Tax", amount: 1.75),
38+
TaxAmount(tax: "Export Tax", amount: 2.30),
39+
TaxAmount(tax: "Income Tax", amount: 2.35)
40+
])
41+
}
42+
43+
func test_multipleConsolidabaleValues_consolidates() {
44+
45+
let importTaxA = TaxAmount(tax: "Import Tax", amount: 3.00)
46+
let salesTaxA = TaxAmount(tax: "Sales Tax", amount: 1.75)
47+
let importTaxB = TaxAmount(tax: "Import Tax", amount: 2.30)
48+
let salesTaxB = TaxAmount(tax: "Sales Tax", amount: 2.35)
49+
50+
let consolidatedTaxes = [
51+
importTaxA,
52+
salesTaxA,
53+
importTaxB,
54+
salesTaxB
55+
].consolidated()
56+
57+
XCTAssertEqual(consolidatedTaxes, [
58+
TaxAmount(tax: "Import Tax", amount: 5.30),
59+
TaxAmount(tax: "Sales Tax", amount: 4.10)
60+
])
61+
}
62+
63+
static var allTests = [
64+
("test_noConsolidabaleValues_doesNotConsolidate", test_noConsolidabaleValues_doesNotConsolidate),
65+
("test_multipleConsolidabaleValues_consolidates", test_multipleConsolidabaleValues_consolidates),
66+
]
67+
}
68+
69+
// MARK: Test Fixtures
70+
71+
struct TaxAmount: Equatable, Consolidatable {
72+
73+
let tax: String
74+
let amount: Decimal
75+
76+
var consolidationGroup: AnyHashable {
77+
return tax
78+
}
79+
80+
func consolidate(with other: Self) -> Self {
81+
return .init(tax: tax, amount: amount + other.amount)
82+
}
83+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import XCTest
2+
3+
#if !canImport(ObjectiveC)
4+
public func allTests() -> [XCTestCaseEntry] {
5+
return [
6+
testCase(ConsolidatableTests.allTests),
7+
]
8+
}
9+
#endif

Tests/LinuxMain.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import XCTest
2+
3+
import ConsolidateTests
4+
5+
var tests = [XCTestCaseEntry]()
6+
tests += ConsolidateTests.allTests()
7+
XCTMain(tests)

0 commit comments

Comments
 (0)