Skip to content

Commit 85bfad4

Browse files
author
Chris
authored
Merge pull request #7 from crelies/dev
refactor(advanced list): replaced switch + any views with group + if
2 parents 82e007c + 0234962 commit 85bfad4

File tree

8 files changed

+117
-45
lines changed

8 files changed

+117
-45
lines changed

Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ let package = Package(
1616
targets: ["AdvancedList"]),
1717
],
1818
dependencies: [
19-
.package(url: "https://github.com/crelies/ListPagination", from: "0.1.0")
19+
.package(url: "https://github.com/crelies/ListPagination", from: "0.1.0"),
20+
.package(url: "https://github.com/nalexn/ViewInspector.git", from: "0.3.8")
2021
],
2122
targets: [
2223
.target(
2324
name: "AdvancedList",
2425
dependencies: ["ListPagination"]),
2526
.testTarget(
2627
name: "AdvancedListTests",
27-
dependencies: ["AdvancedList"]),
28+
dependencies: ["AdvancedList", "ViewInspector"]),
2829
]
2930
)

Sources/AdvancedList/private/Models/AnyDynamicViewContent.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@
77

88
import SwiftUI
99

10-
extension AdvancedList {
11-
struct AnyDynamicViewContent: DynamicViewContent {
12-
private let view: AnyView
10+
struct AnyDynamicViewContent: DynamicViewContent {
11+
private let view: AnyView
1312

14-
private(set) var data: AnyCollection<Any>
15-
var body: some View { view }
13+
private(set) var data: AnyCollection<Any>
14+
var body: some View { view }
1615

17-
init<View: DynamicViewContent>(_ view: View) {
18-
self.view = AnyView(view)
19-
self.data = AnyCollection(view.data.map { $0 as Any })
20-
}
16+
init<View: DynamicViewContent>(_ view: View) {
17+
self.view = AnyView(view)
18+
self.data = AnyCollection(view.data.map { $0 as Any })
2119
}
2220
}

Sources/AdvancedList/public/Models/ListState.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ public enum ListState {
1414
case loading
1515
}
1616

17+
extension ListState {
18+
var error: Error? {
19+
guard case let ListState.error(error) = self else {
20+
return nil
21+
}
22+
return error
23+
}
24+
}
25+
1726
extension ListState: Equatable {
1827
public static func ==(lhs: ListState, rhs: ListState) -> Bool {
1928
switch (lhs, rhs) {

Sources/AdvancedList/public/Views/AdvancedList.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,26 @@ public struct AdvancedList<Data: RandomAccessCollection, Content: View, EmptySta
4040

4141
extension AdvancedList {
4242
public var body: some View {
43-
switch listState.wrappedValue {
44-
case .error(let error):
45-
return AnyView(errorStateView(error))
46-
case .items:
47-
if !data.isEmpty {
48-
return AnyView(
43+
Group {
44+
if listState.wrappedValue == .items {
45+
if !data.isEmpty {
4946
VStack {
5047
getListView()
5148

5249
if isLastItem {
5350
getPaginationStateView()
5451
}
5552
}
56-
)
53+
} else {
54+
emptyStateView()
55+
}
56+
} else if listState.wrappedValue == .loading {
57+
loadingStateView()
5758
} else {
58-
return AnyView(emptyStateView())
59+
listState.wrappedValue.error.map {
60+
errorStateView($0)
61+
}
5962
}
60-
case .loading:
61-
return AnyView(loadingStateView())
6263
}
6364
}
6465
}

Tests/AdvancedListTests/AdvancedListTests.swift

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,75 +10,107 @@ import SwiftUI
1010
import XCTest
1111

1212
final class AdvancedListTests: XCTestCase {
13-
@State private var listState: ListState = .items
14-
15-
private let emptyStateView = Text("Empty")
16-
private let errorStateView = Text("Error")
17-
private let loadingStateView = Text("Loading ...")
18-
19-
override func setUp() {
20-
listState = .items
21-
}
13+
private let emptyStateString = "Empty"
14+
private lazy var emptyStateView = Text(emptyStateString)
15+
private let errorStateString = "Error"
16+
private lazy var errorStateView = Text(errorStateString)
17+
private let loadingStateString = "Loading ..."
18+
private lazy var loadingStateView = Text(loadingStateString)
2219

2320
func testEmptyStateView() {
21+
let emptyListState: Binding<ListState> = .constant(.items)
22+
2423
let items: [String] = []
2524

2625
let view = AdvancedList(items, content: { item in Text(item) },
27-
listState: $listState,
26+
listState: emptyListState,
2827
emptyStateView: { self.emptyStateView },
2928
errorStateView: { _ in self.errorStateView },
3029
loadingStateView: { self.loadingStateView },
3130
pagination: .noPagination)
3231

33-
let body = view.body as? AnyView
34-
XCTAssertNotNil(body)
32+
do {
33+
let inspectableView = try view.body.inspect()
34+
let textString = try inspectableView.group().first?.text().string()
35+
XCTAssertEqual(textString, emptyStateString)
36+
} catch {
37+
XCTFail("\(error)")
38+
}
3539
}
3640

3741
func testNotEmptyStateView() {
38-
let items: [String] = ["MockItem1", "MockItem2"]
42+
let itemsListState: Binding<ListState> = .constant(.items)
43+
44+
let mockItem1 = "MockItem1"
45+
let mockItem2 = "MockItem2"
46+
let items: [String] = [mockItem1, mockItem2]
3947

4048
let view = AdvancedList(items, content: { item in Text(item) },
41-
listState: $listState,
49+
listState: itemsListState,
4250
emptyStateView: { self.emptyStateView },
4351
errorStateView: { _ in self.errorStateView },
4452
loadingStateView: { self.loadingStateView },
4553
pagination: .noPagination)
4654

47-
let body = view.body as? AnyView
48-
XCTAssertNotNil(body)
55+
do {
56+
let inspectableView = try view.body.inspect()
57+
let group = try inspectableView.group().first
58+
let vStack = try group?.vStack()
59+
let list = try vStack?.list(0)
60+
let anyDynamicViewContent = try list?.first?.view(AnyDynamicViewContent.self)
61+
let forEach = try anyDynamicViewContent?.anyView().forEach()
62+
63+
let firstElement = forEach?.first
64+
XCTAssertEqual(try firstElement?.text().string(), mockItem1)
65+
66+
let secondElement = forEach?[1]
67+
XCTAssertEqual(try secondElement?.text().string(), mockItem2)
68+
} catch {
69+
XCTFail("\(error)")
70+
}
4971
}
5072

5173
func testLoadingStateView() {
52-
listState = .loading
74+
let loadingListState: Binding<ListState> = .constant(.loading)
5375

5476
let items: [String] = []
5577

5678
let view = AdvancedList(items, content: { item in Text(item) },
57-
listState: $listState,
79+
listState: loadingListState,
5880
emptyStateView: { self.emptyStateView },
5981
errorStateView: { _ in self.errorStateView },
6082
loadingStateView: { self.loadingStateView },
6183
pagination: .noPagination)
6284

63-
let body = view.body as? AnyView
64-
XCTAssertNotNil(body)
85+
do {
86+
let inspectableView = try view.body.inspect()
87+
let textString = try inspectableView.group().first?.text().string()
88+
XCTAssertEqual(textString, loadingStateString)
89+
} catch {
90+
XCTFail("\(error)")
91+
}
6592
}
6693

6794
func testErrorStateView() {
6895
let error = NSError(domain: "MockDomain", code: 1, userInfo: nil)
69-
listState = .error(error)
96+
let errorListState: Binding<ListState> = .constant(.error(error))
7097

7198
let items: [String] = []
7299

73100
let view = AdvancedList(items, content: { item in Text(item) },
74-
listState: $listState,
101+
listState: errorListState,
75102
emptyStateView: { self.emptyStateView },
76103
errorStateView: { _ in self.errorStateView },
77104
loadingStateView: { self.loadingStateView },
78105
pagination: .noPagination)
79106

80-
let body = view.body as? AnyView
81-
XCTAssertNotNil(body)
107+
do {
108+
let inspectableView = try view.body.inspect()
109+
let textString = try inspectableView.group().first?.text().string()
110+
XCTAssertEqual(textString, errorStateString)
111+
} catch {
112+
XCTFail("\(error)")
113+
}
82114
}
83115

84116
static var allTests = [
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// AdvancedList+Inspectable.swift
3+
// AdvancedListTests
4+
//
5+
// Created by Christian Elies on 22.02.20.
6+
//
7+
8+
@testable import AdvancedList
9+
import ViewInspector
10+
11+
extension AdvancedList: Inspectable {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// AnyDynamicViewContent+Inspectable.swift
3+
// AdvancedListTests
4+
//
5+
// Created by Christian Elies on 22.02.20.
6+
//
7+
8+
@testable import AdvancedList
9+
import ViewInspector
10+
11+
extension AnyDynamicViewContent: Inspectable {}

0 commit comments

Comments
 (0)