Skip to content

Commit 0df3d35

Browse files
Add unit test for mail validation, ipa upload info and version compare
1 parent aee52c6 commit 0df3d35

4 files changed

Lines changed: 551 additions & 0 deletions

File tree

AppBox.xcodeproj/project.pbxproj

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
AA11BB22CC33DD44EE550012 /* MobileProvisionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550002 /* MobileProvisionTests.m */; };
100100
AA11BB22CC33DD44EE550013 /* KeychainHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550003 /* KeychainHandlerTests.m */; };
101101
AA11BB22CC33DD44EE550014 /* UserDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550004 /* UserDataTests.m */; };
102+
AA11BB22CC33DD44EE550015 /* MailHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550005 /* MailHandlerTests.m */; };
103+
AA11BB22CC33DD44EE550016 /* UpdateHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11BB22CC33DD44EE550006 /* UpdateHandlerTests.m */; };
102104
/* End PBXBuildFile section */
103105

104106
/* Begin PBXContainerItemProxy section */
@@ -300,6 +302,8 @@
300302
AA11BB22CC33DD44EE550002 /* MobileProvisionTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MobileProvisionTests.m; path = Common/MobileProvision/MobileProvisionTests.m; sourceTree = "<group>"; };
301303
AA11BB22CC33DD44EE550003 /* KeychainHandlerTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = KeychainHandlerTests.m; path = Common/KeychainHandler/KeychainHandlerTests.m; sourceTree = "<group>"; };
302304
AA11BB22CC33DD44EE550004 /* UserDataTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = UserDataTests.m; path = Common/UserManager/UserDataTests.m; sourceTree = "<group>"; };
305+
AA11BB22CC33DD44EE550005 /* MailHandlerTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MailHandlerTests.m; path = Common/MailHandler/MailHandlerTests.m; sourceTree = "<group>"; };
306+
AA11BB22CC33DD44EE550006 /* UpdateHandlerTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = UpdateHandlerTests.m; path = Common/UpdateHandler/UpdateHandlerTests.m; sourceTree = "<group>"; };
303307
/* End PBXFileReference section */
304308

305309
/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */
@@ -401,6 +405,22 @@
401405
name = UserManager;
402406
sourceTree = "<group>";
403407
};
408+
AA11BB22CC33DD44EE550027 /* MailHandler */ = {
409+
isa = PBXGroup;
410+
children = (
411+
AA11BB22CC33DD44EE550005 /* MailHandlerTests.m */,
412+
);
413+
name = MailHandler;
414+
sourceTree = "<group>";
415+
};
416+
AA11BB22CC33DD44EE550028 /* UpdateHandler */ = {
417+
isa = PBXGroup;
418+
children = (
419+
AA11BB22CC33DD44EE550006 /* UpdateHandlerTests.m */,
420+
);
421+
name = UpdateHandler;
422+
sourceTree = "<group>";
423+
};
404424
AA11BB22CC33DD44EE550021 /* Common */ = {
405425
isa = PBXGroup;
406426
children = (
@@ -409,6 +429,8 @@
409429
AA11BB22CC33DD44EE550023 /* MobileProvision */,
410430
AA11BB22CC33DD44EE550024 /* KeychainHandler */,
411431
AA11BB22CC33DD44EE550025 /* UserManager */,
432+
AA11BB22CC33DD44EE550027 /* MailHandler */,
433+
AA11BB22CC33DD44EE550028 /* UpdateHandler */,
412434
);
413435
name = Common;
414436
sourceTree = "<group>";
@@ -1143,6 +1165,8 @@
11431165
AA11BB22CC33DD44EE550012 /* MobileProvisionTests.m in Sources */,
11441166
AA11BB22CC33DD44EE550013 /* KeychainHandlerTests.m in Sources */,
11451167
AA11BB22CC33DD44EE550014 /* UserDataTests.m in Sources */,
1168+
AA11BB22CC33DD44EE550015 /* MailHandlerTests.m in Sources */,
1169+
AA11BB22CC33DD44EE550016 /* UpdateHandlerTests.m in Sources */,
11461170
);
11471171
runOnlyForDeploymentPostprocessing = 0;
11481172
};
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
//
2+
// MailHandlerTests.m
3+
// AppBoxTests
4+
//
5+
// Created by AppBox on 29/05/26.
6+
// Copyright © 2026 Developer Insider. All rights reserved.
7+
//
8+
9+
#import <XCTest/XCTest.h>
10+
#import "MailHandler.h"
11+
#import "IPAUploadInfo.h"
12+
13+
@interface MailHandlerTests : XCTestCase
14+
@end
15+
16+
@implementation MailHandlerTests
17+
18+
#pragma mark - isValidEmail: Tests (Single Email Regex)
19+
20+
- (void)testIsValidEmail_SimpleValidEmail {
21+
XCTAssertTrue([MailHandler isValidEmail:@"user@example.com"]);
22+
}
23+
24+
- (void)testIsValidEmail_WithSubdomain {
25+
XCTAssertTrue([MailHandler isValidEmail:@"user@mail.example.com"]);
26+
}
27+
28+
- (void)testIsValidEmail_WithPlusTag {
29+
XCTAssertTrue([MailHandler isValidEmail:@"user+tag@example.com"]);
30+
}
31+
32+
- (void)testIsValidEmail_WithDots {
33+
XCTAssertTrue([MailHandler isValidEmail:@"first.last@example.com"]);
34+
}
35+
36+
- (void)testIsValidEmail_WithUnderscore {
37+
XCTAssertTrue([MailHandler isValidEmail:@"user_name@example.com"]);
38+
}
39+
40+
- (void)testIsValidEmail_WithHyphenInDomain {
41+
XCTAssertTrue([MailHandler isValidEmail:@"user@my-company.com"]);
42+
}
43+
44+
- (void)testIsValidEmail_WithNumbers {
45+
XCTAssertTrue([MailHandler isValidEmail:@"user123@example456.com"]);
46+
}
47+
48+
- (void)testIsValidEmail_WithPercentSign {
49+
XCTAssertTrue([MailHandler isValidEmail:@"user%name@example.com"]);
50+
}
51+
52+
- (void)testIsValidEmail_WithLongTLD {
53+
XCTAssertTrue([MailHandler isValidEmail:@"user@example.technology"]);
54+
}
55+
56+
- (void)testIsValidEmail_WithTwoLetterTLD {
57+
XCTAssertTrue([MailHandler isValidEmail:@"user@example.io"]);
58+
}
59+
60+
- (void)testIsValidEmail_EmptyString_ReturnsNO {
61+
XCTAssertFalse([MailHandler isValidEmail:@""]);
62+
}
63+
64+
- (void)testIsValidEmail_NoAtSign_ReturnsNO {
65+
XCTAssertFalse([MailHandler isValidEmail:@"userexample.com"]);
66+
}
67+
68+
- (void)testIsValidEmail_NoDomain_ReturnsNO {
69+
XCTAssertFalse([MailHandler isValidEmail:@"user@"]);
70+
}
71+
72+
- (void)testIsValidEmail_NoUsername_ReturnsNO {
73+
XCTAssertFalse([MailHandler isValidEmail:@"@example.com"]);
74+
}
75+
76+
- (void)testIsValidEmail_NoTLD_ReturnsNO {
77+
XCTAssertFalse([MailHandler isValidEmail:@"user@example"]);
78+
}
79+
80+
- (void)testIsValidEmail_SpacesInEmail_ReturnsNO {
81+
XCTAssertFalse([MailHandler isValidEmail:@"user @example.com"]);
82+
}
83+
84+
- (void)testIsValidEmail_DoubleAtSign_ReturnsNO {
85+
XCTAssertFalse([MailHandler isValidEmail:@"user@@example.com"]);
86+
}
87+
88+
- (void)testIsValidEmail_DotAtEnd_ReturnsNO {
89+
XCTAssertFalse([MailHandler isValidEmail:@"user@example."]);
90+
}
91+
92+
- (void)testIsValidEmail_JustText_ReturnsNO {
93+
XCTAssertFalse([MailHandler isValidEmail:@"plaintext"]);
94+
}
95+
96+
- (void)testIsValidEmail_SingleCharTLD_ReturnsNO {
97+
XCTAssertFalse([MailHandler isValidEmail:@"user@example.c"]);
98+
}
99+
100+
- (void)testIsValidEmail_MultipleAtSigns_ReturnsNO {
101+
XCTAssertFalse([MailHandler isValidEmail:@"user@name@example.com"]);
102+
}
103+
104+
#pragma mark - isAllValidEmail: Tests (Comma-Separated Emails)
105+
106+
- (void)testIsAllValidEmail_SingleEmail {
107+
XCTAssertTrue([MailHandler isAllValidEmail:@"user@example.com"]);
108+
}
109+
110+
- (void)testIsAllValidEmail_TwoEmails {
111+
XCTAssertTrue([MailHandler isAllValidEmail:@"user@example.com,admin@test.io"]);
112+
}
113+
114+
- (void)testIsAllValidEmail_MultipleEmails {
115+
XCTAssertTrue([MailHandler isAllValidEmail:@"a@b.com,c@d.org,e@f.net"]);
116+
}
117+
118+
- (void)testIsAllValidEmail_WithSpacesAfterComma {
119+
XCTAssertTrue([MailHandler isAllValidEmail:@"user@example.com, admin@test.io"]);
120+
}
121+
122+
- (void)testIsAllValidEmail_EmptyString {
123+
XCTAssertTrue([MailHandler isAllValidEmail:@""]);
124+
}
125+
126+
- (void)testIsAllValidEmail_InvalidEmail_ReturnsNO {
127+
XCTAssertFalse([MailHandler isAllValidEmail:@"notanemail"]);
128+
}
129+
130+
- (void)testIsAllValidEmail_MixedValidAndInvalid_ReturnsNO {
131+
XCTAssertFalse([MailHandler isAllValidEmail:@"user@example.com,invalid"]);
132+
}
133+
134+
- (void)testIsAllValidEmail_DoubleComma_ReturnsNO {
135+
XCTAssertFalse([MailHandler isAllValidEmail:@"user@example.com,,admin@test.io"]);
136+
}
137+
138+
#pragma mark - parseMessage:forIPAUploadInfo: Tests
139+
140+
- (void)testParseMessage_ReplacesBuildName {
141+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
142+
info.name = @"MyApp";
143+
info.version = @"1.0";
144+
info.build = @"42";
145+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/app"];
146+
147+
NSString *result = [MailHandler parseMessage:@"New build: {BUILD_NAME}" forIPAUploadInfo:info];
148+
XCTAssertTrue([result containsString:@"MyApp"]);
149+
XCTAssertFalse([result containsString:@"{BUILD_NAME}"]);
150+
}
151+
152+
- (void)testParseMessage_ReplacesBuildNumber {
153+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
154+
info.name = @"TestApp";
155+
info.version = @"2.0";
156+
info.build = @"99";
157+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/app"];
158+
159+
NSString *result = [MailHandler parseMessage:@"Build #{BUILD_NUMBER}" forIPAUploadInfo:info];
160+
XCTAssertTrue([result containsString:@"99"]);
161+
XCTAssertFalse([result containsString:@"{BUILD_NUMBER}"]);
162+
}
163+
164+
- (void)testParseMessage_ReplacesBuildVersion {
165+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
166+
info.name = @"TestApp";
167+
info.version = @"3.5.1";
168+
info.build = @"1";
169+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/app"];
170+
171+
NSString *result = [MailHandler parseMessage:@"Version: {BUILD_VERSION}" forIPAUploadInfo:info];
172+
XCTAssertTrue([result containsString:@"3.5.1"]);
173+
XCTAssertFalse([result containsString:@"{BUILD_VERSION}"]);
174+
}
175+
176+
- (void)testParseMessage_ReplacesShareURL {
177+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
178+
info.name = @"TestApp";
179+
info.version = @"1.0";
180+
info.build = @"1";
181+
info.appShortShareableURL = [NSURL URLWithString:@"https://getappbox.com/share/abc123"];
182+
183+
NSString *result = [MailHandler parseMessage:@"Download: {SHARE_URL}" forIPAUploadInfo:info];
184+
XCTAssertTrue([result containsString:@"https://getappbox.com/share/abc123"]);
185+
XCTAssertFalse([result containsString:@"{SHARE_URL}"]);
186+
}
187+
188+
- (void)testParseMessage_AllPlaceholders {
189+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
190+
info.name = @"AppBox";
191+
info.version = @"4.2.0";
192+
info.build = @"200";
193+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/link"];
194+
195+
NSString *template = @"{BUILD_NAME} v{BUILD_VERSION} ({BUILD_NUMBER}) - {SHARE_URL}";
196+
NSString *result = [MailHandler parseMessage:template forIPAUploadInfo:info];
197+
XCTAssertTrue([result containsString:@"AppBox"]);
198+
XCTAssertTrue([result containsString:@"4.2.0"]);
199+
XCTAssertTrue([result containsString:@"200"]);
200+
XCTAssertTrue([result containsString:@"https://example.com/link"]);
201+
}
202+
203+
- (void)testParseMessage_WithoutShareURL_AppendsURL {
204+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
205+
info.name = @"TestApp";
206+
info.version = @"1.0";
207+
info.build = @"1";
208+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/download"];
209+
210+
NSString *result = [MailHandler parseMessage:@"Build is ready!" forIPAUploadInfo:info];
211+
XCTAssertTrue([result containsString:@"Build is ready!"]);
212+
XCTAssertTrue([result containsString:@"https://example.com/download"]);
213+
}
214+
215+
- (void)testParseMessage_WithShareURL_DoesNotAppendDuplicate {
216+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
217+
info.name = @"TestApp";
218+
info.version = @"1.0";
219+
info.build = @"1";
220+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com/dl"];
221+
222+
NSString *result = [MailHandler parseMessage:@"Link: {SHARE_URL}" forIPAUploadInfo:info];
223+
// Should only appear once since {SHARE_URL} was explicitly used
224+
NSUInteger count = [[result componentsSeparatedByString:@"https://example.com/dl"] count] - 1;
225+
XCTAssertEqual(count, 1);
226+
}
227+
228+
- (void)testParseMessage_NoPlaceholders_ReturnsOriginalWithURL {
229+
IPAUploadInfo *info = [[IPAUploadInfo alloc] initEmpty];
230+
info.name = @"TestApp";
231+
info.version = @"1.0";
232+
info.build = @"1";
233+
info.appShortShareableURL = [NSURL URLWithString:@"https://example.com"];
234+
235+
NSString *result = [MailHandler parseMessage:@"Hello World" forIPAUploadInfo:info];
236+
XCTAssertTrue([result hasPrefix:@"Hello World"]);
237+
}
238+
239+
@end

0 commit comments

Comments
 (0)