feature/v1
swift 119 lines 3.31 KB
Raw
1 //
2 // JomloCollectionViewTests.swift
3 // JomloCollectionView
4 //
5 // Created by Seto Elkahfi on 2026-01-27.
6 // Copyright © 2026 Seto Elkahfi. All rights reserved.
7 //
8
9 import Testing
10 import UIKit
11
12 @testable import JomloCollectionView
13
14 @MainActor
15 struct JomloCollectionViewTests {
16
17 @Test("JomloCollectionViewController initializes with empty sections")
18 func emptyInitialization() {
19 let vc = JomloCollectionViewController(sections: [])
20 vc.loadViewIfNeeded()
21 #expect(vc.sections.isEmpty)
22 #expect(vc.collectionView.superview != nil)
23 }
24
25 @Test("JomloCollectionViewController accepts sections")
26 func sectionsAreSet() {
27 let section = MockSection(id: "test")
28 let vc = JomloCollectionViewController(sections: [section])
29 vc.loadViewIfNeeded()
30 #expect(vc.sections.count == 1)
31 }
32
33 @Test("JomloAnimator stops after all visible cells animated")
34 func animatorStops() {
35 var animationCount = 0
36 let animator = JomloAnimator { _, _, _ in
37 animationCount += 1
38 }
39 #expect(animationCount == 0)
40 // Animator created successfully
41 }
42
43 @Test("AnyJomloItem wraps items correctly")
44 func anyItemWrapping() {
45 let item = MockItem(id: "item1", title: "Test")
46 let wrapped = AnyJomloItem(item)
47 #expect(wrapped.itemIdentifier == "item1")
48 }
49
50 @Test("JomloLayoutFactory creates hero section")
51 func heroLayout() {
52 let section = JomloLayoutFactory.hero()
53 #expect(section.orthogonalScrollingBehavior == .groupPagingCentered)
54 }
55
56 @Test("JomloLayoutFactory creates horizontal shelf")
57 func shelfLayout() {
58 let section = JomloLayoutFactory.horizontalShelf()
59 #expect(section.orthogonalScrollingBehavior == .continuous)
60 }
61
62 @Test("Section header view configures correctly")
63 func headerConfiguration() {
64 let header = JomloSectionHeaderView(frame: .zero)
65 header.configure(title: "Trending", actionTitle: "See All")
66 #expect(header.titleLabel.text == "Trending")
67 #expect(header.actionButton.isHidden == false)
68 }
69
70 @Test("Section header hides action button when nil")
71 func headerNoAction() {
72 let header = JomloSectionHeaderView(frame: .zero)
73 header.configure(title: "Movies")
74 #expect(header.actionButton.isHidden == true)
75 }
76 }
77
78 // MARK: - Test Helpers
79
80 @MainActor
81 final class MockSection: JomloSection {
82 let identifier: JomloSectionID
83 var onReloadNeeded: (@MainActor @Sendable () -> Void)?
84
85 init(id: String) {
86 self.identifier = JomloSectionID(id)
87 }
88
89 func items() -> [any JomloItem] {
90 [MockItem(id: "1", title: "Mock")]
91 }
92
93 func layoutSection(environment: NSCollectionLayoutEnvironment, sectionIndex: Int)
94 -> NSCollectionLayoutSection
95 {
96 JomloLayoutFactory.list()
97 }
98
99 func cell(for item: any JomloItem, in collectionView: UICollectionView, at indexPath: IndexPath)
100 -> UICollectionViewCell
101 {
102 UICollectionViewCell()
103 }
104 }
105
106 struct MockItem: JomloItem {
107 let id: String
108 let title: String
109
110 nonisolated var itemIdentifier: String { id }
111
112 nonisolated func hash(into hasher: inout Hasher) {
113 hasher.combine(id)
114 }
115
116 nonisolated static func == (lhs: MockItem, rhs: MockItem) -> Bool {
117 lhs.id == rhs.id
118 }
119 }