Skip to content

Commit f581d18

Browse files
committed
Add tests and update deployment target to iOS 12.0
- Add 18 test cases for modifier input validation - Update minimum deployment target to iOS 12.0 - Add post_install hook to ensure pods compatibility - Fix libarclite error on Xcode 16+
1 parent d0185e9 commit f581d18

File tree

4 files changed

+241
-16
lines changed

4 files changed

+241
-16
lines changed

Hero.xcodeproj/project.pbxproj

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
B35264CF2454FEF300D33861 /* Locale+Hero.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35264CD2454FEF300D33861 /* Locale+Hero.swift */; };
133133
B383074925D1041A00B7A0D8 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B383074825D1041A00B7A0D8 /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
134134
B383074B25D1042C00B7A0D8 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B383074A25D1042C00B7A0D8 /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
135+
D347BDBC2ED41295009608AE /* HeroModifierInputValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D347BDBB2ED41295009608AE /* HeroModifierInputValidationTests.swift */; };
135136
DBA05BB41A704A4A17967918 /* Pods_HeroTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 841FFA357ACB279D3F74CDEE /* Pods_HeroTests.framework */; };
136137
F482F0BE235D7808002E97ED /* UIColor+HexString.swift in Sources */ = {isa = PBXBuildFile; fileRef = F482F0BD235D7808002E97ED /* UIColor+HexString.swift */; };
137138
F482F0BF235D7808002E97ED /* UIColor+HexString.swift in Sources */ = {isa = PBXBuildFile; fileRef = F482F0BD235D7808002E97ED /* UIColor+HexString.swift */; };
@@ -294,6 +295,7 @@
294295
B383074A25D1042C00B7A0D8 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS14.3.sdk/System/Library/Frameworks/SwiftUI.framework; sourceTree = DEVELOPER_DIR; };
295296
C377744CBFF1E24426E80F55 /* Pods-HeroExamples.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HeroExamples.release.xcconfig"; path = "Pods/Target Support Files/Pods-HeroExamples/Pods-HeroExamples.release.xcconfig"; sourceTree = "<group>"; };
296297
C51A6465EC2CB38D82F28B93 /* Pods-HeroTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HeroTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-HeroTests/Pods-HeroTests.debug.xcconfig"; sourceTree = "<group>"; };
298+
D347BDBB2ED41295009608AE /* HeroModifierInputValidationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeroModifierInputValidationTests.swift; sourceTree = "<group>"; };
297299
EEE340F89FF0A49DD23A5A6E /* Pods_HeroExamples.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HeroExamples.framework; sourceTree = BUILT_PRODUCTS_DIR; };
298300
F482F0BD235D7808002E97ED /* UIColor+HexString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+HexString.swift"; sourceTree = "<group>"; };
299301
F482F0C5235D7C4C002E97ED /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = "<group>"; };
@@ -590,6 +592,7 @@
590592
AF1E1B521E66822C00ECE039 /* Tests */ = {
591593
isa = PBXGroup;
592594
children = (
595+
D347BDBB2ED41295009608AE /* HeroModifierInputValidationTests.swift */,
593596
AF1E1B531E66822C00ECE039 /* HeroTests.swift */,
594597
AF1E1B551E66822C00ECE039 /* Info.plist */,
595598
);
@@ -896,10 +899,14 @@
896899
inputFileListPaths = (
897900
"${PODS_ROOT}/Target Support Files/Pods-HeroExamples/Pods-HeroExamples-frameworks-${CONFIGURATION}-input-files.xcfilelist",
898901
);
902+
inputPaths = (
903+
);
899904
name = "[CP] Embed Pods Frameworks";
900905
outputFileListPaths = (
901906
"${PODS_ROOT}/Target Support Files/Pods-HeroExamples/Pods-HeroExamples-frameworks-${CONFIGURATION}-output-files.xcfilelist",
902907
);
908+
outputPaths = (
909+
);
903910
runOnlyForDeploymentPostprocessing = 0;
904911
shellPath = /bin/sh;
905912
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HeroExamples/Pods-HeroExamples-frameworks.sh\"\n";
@@ -1126,6 +1133,7 @@
11261133
isa = PBXSourcesBuildPhase;
11271134
buildActionMask = 2147483647;
11281135
files = (
1136+
D347BDBC2ED41295009608AE /* HeroModifierInputValidationTests.swift in Sources */,
11291137
AF1E1B541E66822C00ECE039 /* HeroTests.swift in Sources */,
11301138
);
11311139
runOnlyForDeploymentPostprocessing = 0;
@@ -1294,9 +1302,7 @@
12941302
buildSettings = {
12951303
APPLICATION_EXTENSION_API_ONLY = YES;
12961304
CLANG_ENABLE_MODULES = YES;
1297-
CODE_SIGN_IDENTITY = "";
1298-
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
1299-
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
1305+
CODE_SIGN_IDENTITY = "Apple Development";
13001306
CURRENT_PROJECT_VERSION = 1;
13011307
DEFINES_MODULE = YES;
13021308
DEVELOPMENT_TEAM = "";
@@ -1305,7 +1311,7 @@
13051311
DYLIB_INSTALL_NAME_BASE = "@rpath";
13061312
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
13071313
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1308-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1314+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
13091315
LD_RUNPATH_SEARCH_PATHS = (
13101316
"$(inherited)",
13111317
"@executable_path/Frameworks",
@@ -1327,7 +1333,7 @@
13271333
buildSettings = {
13281334
APPLICATION_EXTENSION_API_ONLY = YES;
13291335
CLANG_ENABLE_MODULES = YES;
1330-
CODE_SIGN_IDENTITY = "";
1336+
CODE_SIGN_IDENTITY = "Apple Development";
13311337
CURRENT_PROJECT_VERSION = 1;
13321338
DEFINES_MODULE = YES;
13331339
DEVELOPMENT_TEAM = "";
@@ -1336,7 +1342,7 @@
13361342
DYLIB_INSTALL_NAME_BASE = "@rpath";
13371343
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
13381344
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1339-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1345+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
13401346
LD_RUNPATH_SEARCH_PATHS = (
13411347
"$(inherited)",
13421348
"@executable_path/Frameworks",
@@ -1402,7 +1408,7 @@
14021408
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
14031409
GCC_WARN_UNUSED_FUNCTION = YES;
14041410
GCC_WARN_UNUSED_VARIABLE = YES;
1405-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1411+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
14061412
MARKETING_VERSION = 1.6.4;
14071413
MTL_ENABLE_DEBUG_INFO = YES;
14081414
ONLY_ACTIVE_ARCH = YES;
@@ -1458,7 +1464,7 @@
14581464
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
14591465
GCC_WARN_UNUSED_FUNCTION = YES;
14601466
GCC_WARN_UNUSED_VARIABLE = YES;
1461-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1467+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
14621468
MARKETING_VERSION = 1.6.4;
14631469
MTL_ENABLE_DEBUG_INFO = NO;
14641470
SDKROOT = iphoneos;
@@ -1477,7 +1483,7 @@
14771483
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
14781484
DEVELOPMENT_TEAM = "";
14791485
INFOPLIST_FILE = "$(SRCROOT)/Examples/Resources/Info.plist";
1480-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1486+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
14811487
LD_RUNPATH_SEARCH_PATHS = (
14821488
"$(inherited)",
14831489
"@executable_path/Frameworks",
@@ -1509,7 +1515,7 @@
15091515
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
15101516
DEVELOPMENT_TEAM = "";
15111517
INFOPLIST_FILE = "$(SRCROOT)/Examples/Resources/Info.plist";
1512-
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
1518+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
15131519
LD_RUNPATH_SEARCH_PATHS = (
15141520
"$(inherited)",
15151521
"@executable_path/Frameworks",
@@ -1542,7 +1548,7 @@
15421548
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
15431549
DEVELOPMENT_TEAM = "";
15441550
INFOPLIST_FILE = Tests/Info.plist;
1545-
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
1551+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
15461552
LD_RUNPATH_SEARCH_PATHS = (
15471553
"$(inherited)",
15481554
"@executable_path/Frameworks",
@@ -1576,7 +1582,7 @@
15761582
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
15771583
DEVELOPMENT_TEAM = "";
15781584
INFOPLIST_FILE = Tests/Info.plist;
1579-
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
1585+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
15801586
LD_RUNPATH_SEARCH_PATHS = (
15811587
"$(inherited)",
15821588
"@executable_path/Frameworks",

Podfile

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22

33
target 'HeroExamples' do
4-
platform :ios, '10.0'
4+
platform :ios, '12.0'
55
use_frameworks!
66
pod 'CollectionKit', :inhibit_warnings => true
77

@@ -11,6 +11,19 @@ target 'HeroExamples' do
1111
end
1212

1313
target 'HeroTvOSExamples' do
14-
platform :tvos, '10.0'
14+
platform :tvos, '12.0'
1515
use_frameworks!
1616
end
17+
18+
post_install do |installer|
19+
installer.pods_project.targets.each do |target|
20+
target.build_configurations.each do |config|
21+
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 12.0
22+
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
23+
end
24+
if config.build_settings['TVOS_DEPLOYMENT_TARGET'].to_f < 12.0
25+
config.build_settings['TVOS_DEPLOYMENT_TARGET'] = '12.0'
26+
end
27+
end
28+
end
29+
end

Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ SPEC REPOS:
1313
SPEC CHECKSUMS:
1414
CollectionKit: 8f01e7629185bb81072c4aa734d105df5c2d1c8b
1515

16-
PODFILE CHECKSUM: 5c14933c915eeee6fbe5ecdd950d3da01c4a0a86
16+
PODFILE CHECKSUM: 4b47eb3c33ba27c86d91d0651803ab1d0a102e64
1717

18-
COCOAPODS: 1.11.3
18+
COCOAPODS: 1.16.2
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in
13+
// all copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
// THE SOFTWARE.
22+
23+
#if canImport(UIKit)
24+
import XCTest
25+
import Hero
26+
27+
class HeroModifierInputValidationTests: XCTestCase {
28+
29+
// MARK: - Position Modifier Tests
30+
31+
func testPositionWithValidValues() {
32+
let modifier = HeroModifier.position(CGPoint(x: 100, y: 200))
33+
let state: HeroTargetState = [modifier]
34+
XCTAssertEqual(state.position, CGPoint(x: 100, y: 200))
35+
}
36+
37+
func testPositionWithInvalidValues() {
38+
let nanModifier = HeroModifier.position(CGPoint(x: CGFloat.nan, y: 200))
39+
let nanState: HeroTargetState = [nanModifier]
40+
XCTAssertNil(nanState.position, "Position should not be set when value is NaN")
41+
42+
let infModifier = HeroModifier.position(CGPoint(x: CGFloat.infinity, y: 200))
43+
let infState: HeroTargetState = [infModifier]
44+
XCTAssertNil(infState.position, "Position should not be set when value is Infinity")
45+
}
46+
47+
// MARK: - Size Modifier Tests
48+
49+
func testSizeWithValidValues() {
50+
let modifier = HeroModifier.size(CGSize(width: 100, height: 200))
51+
let state: HeroTargetState = [modifier]
52+
XCTAssertEqual(state.size, CGSize(width: 100, height: 200))
53+
}
54+
55+
func testSizeWithInvalidValues() {
56+
let nanModifier = HeroModifier.size(CGSize(width: CGFloat.nan, height: 200))
57+
let nanState: HeroTargetState = [nanModifier]
58+
XCTAssertNil(nanState.size, "Size should not be set when value is NaN")
59+
60+
let infModifier = HeroModifier.size(CGSize(width: 100, height: CGFloat.infinity))
61+
let infState: HeroTargetState = [infModifier]
62+
XCTAssertNil(infState.size, "Size should not be set when value is Infinity")
63+
}
64+
65+
// MARK: - Perspective Modifier Tests
66+
67+
func testPerspectiveWithValidValue() {
68+
let modifier = HeroModifier.perspective(500)
69+
let state: HeroTargetState = [modifier]
70+
XCTAssertNotNil(state.transform, "Transform should be set with valid perspective")
71+
if let m34 = state.transform?.m34 {
72+
XCTAssertEqual(Double(m34), 1.0 / -500.0, accuracy: 0.0001)
73+
}
74+
}
75+
76+
func testPerspectiveWithInvalidValues() {
77+
let zeroModifier = HeroModifier.perspective(0)
78+
let zeroState: HeroTargetState = [zeroModifier]
79+
XCTAssertNil(zeroState.transform, "Transform should not be set when perspective is zero")
80+
81+
let nanModifier = HeroModifier.perspective(CGFloat.nan)
82+
let nanState: HeroTargetState = [nanModifier]
83+
XCTAssertNil(nanState.transform, "Transform should not be set when perspective is NaN")
84+
85+
let infModifier = HeroModifier.perspective(CGFloat.infinity)
86+
let infState: HeroTargetState = [infModifier]
87+
XCTAssertNil(infState.transform, "Transform should not be set when perspective is Infinity")
88+
}
89+
90+
// MARK: - Scale Modifier Tests
91+
92+
func testScaleWithValidValues() {
93+
let modifier = HeroModifier.scale(x: 2, y: 3, z: 1)
94+
let state: HeroTargetState = [modifier]
95+
XCTAssertNotNil(state.transform, "Transform should be set with valid scale values")
96+
}
97+
98+
func testScaleWithInvalidValues() {
99+
let nanModifier = HeroModifier.scale(x: CGFloat.nan, y: 1, z: 1)
100+
let nanState: HeroTargetState = [nanModifier]
101+
XCTAssertNil(nanState.transform, "Transform should not be set when value is NaN")
102+
103+
let infModifier = HeroModifier.scale(x: 1, y: CGFloat.infinity, z: 1)
104+
let infState: HeroTargetState = [infModifier]
105+
XCTAssertNil(infState.transform, "Transform should not be set when value is Infinity")
106+
}
107+
108+
// MARK: - Translate Modifier Tests
109+
110+
func testTranslateWithValidValues() {
111+
let modifier = HeroModifier.translate(x: 50, y: 100, z: 0)
112+
let state: HeroTargetState = [modifier]
113+
XCTAssertNotNil(state.transform, "Transform should be set with valid translate values")
114+
}
115+
116+
func testTranslateWithInvalidValues() {
117+
let nanModifier = HeroModifier.translate(x: 50, y: 100, z: CGFloat.nan)
118+
let nanState: HeroTargetState = [nanModifier]
119+
XCTAssertNil(nanState.transform, "Transform should not be set when value is NaN")
120+
121+
let infModifier = HeroModifier.translate(x: CGFloat.infinity, y: 100, z: 0)
122+
let infState: HeroTargetState = [infModifier]
123+
XCTAssertNil(infState.transform, "Transform should not be set when value is Infinity")
124+
}
125+
126+
// MARK: - Rotate Modifier Tests
127+
128+
func testRotateWithValidValues() {
129+
let modifier = HeroModifier.rotate(x: 0, y: 0, z: .pi)
130+
let state: HeroTargetState = [modifier]
131+
XCTAssertNotNil(state.transform, "Transform should be set with valid rotate values")
132+
}
133+
134+
func testRotateWithInvalidValues() {
135+
let nanModifier = HeroModifier.rotate(x: CGFloat.nan, y: 0, z: 0)
136+
let nanState: HeroTargetState = [nanModifier]
137+
XCTAssertNil(nanState.transform, "Transform should not be set when value is NaN")
138+
139+
let infModifier = HeroModifier.rotate(x: 0, y: 0, z: CGFloat.infinity)
140+
let infState: HeroTargetState = [infModifier]
141+
XCTAssertNil(infState.transform, "Transform should not be set when value is Infinity")
142+
}
143+
144+
// MARK: - Duration Modifier Tests
145+
146+
func testDurationWithValidValues() {
147+
let validModifier = HeroModifier.duration(0.5)
148+
let validState: HeroTargetState = [validModifier]
149+
XCTAssertEqual(validState.duration, 0.5)
150+
151+
let infModifier = HeroModifier.duration(.infinity)
152+
let infState: HeroTargetState = [infModifier]
153+
XCTAssertEqual(infState.duration, .infinity, "Infinity should be allowed for duration")
154+
}
155+
156+
func testDurationWithInvalidValues() {
157+
let nanModifier = HeroModifier.duration(TimeInterval.nan)
158+
let nanState: HeroTargetState = [nanModifier]
159+
XCTAssertNil(nanState.duration, "Duration should not be set when value is NaN")
160+
161+
let negativeModifier = HeroModifier.duration(-1.0)
162+
let negativeState: HeroTargetState = [negativeModifier]
163+
XCTAssertNil(negativeState.duration, "Duration should not be set when value is negative")
164+
}
165+
166+
// MARK: - Delay Modifier Tests
167+
168+
func testDelayWithValidValue() {
169+
let modifier = HeroModifier.delay(0.3)
170+
let state: HeroTargetState = [modifier]
171+
XCTAssertEqual(state.delay, 0.3)
172+
}
173+
174+
func testDelayWithInvalidValues() {
175+
let nanModifier = HeroModifier.delay(TimeInterval.nan)
176+
let nanState: HeroTargetState = [nanModifier]
177+
XCTAssertNil(nanState.delay, "Delay should not be set when value is NaN")
178+
179+
let infModifier = HeroModifier.delay(TimeInterval.infinity)
180+
let infState: HeroTargetState = [infModifier]
181+
XCTAssertNil(infState.delay, "Delay should not be set when value is Infinity")
182+
183+
let negativeModifier = HeroModifier.delay(-0.5)
184+
let negativeState: HeroTargetState = [negativeModifier]
185+
XCTAssertNil(negativeState.delay, "Delay should not be set when value is negative")
186+
}
187+
188+
// MARK: - Arc Modifier Tests
189+
190+
func testArcWithValidIntensity() {
191+
let modifier = HeroModifier.arc(intensity: 1)
192+
let state: HeroTargetState = [modifier]
193+
XCTAssertEqual(state.arc, 1)
194+
}
195+
196+
func testArcWithInvalidValues() {
197+
let nanModifier = HeroModifier.arc(intensity: CGFloat.nan)
198+
let nanState: HeroTargetState = [nanModifier]
199+
XCTAssertNil(nanState.arc, "Arc should not be set when intensity is NaN")
200+
201+
let infModifier = HeroModifier.arc(intensity: CGFloat.infinity)
202+
let infState: HeroTargetState = [infModifier]
203+
XCTAssertNil(infState.arc, "Arc should not be set when intensity is Infinity")
204+
}
205+
}
206+
#endif

0 commit comments

Comments
 (0)