Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to domainURIPrefix for FIRDynamicLinkComponents #2119

Merged
merged 11 commits into from Nov 29, 2018
6 changes: 6 additions & 0 deletions Example/DynamicLinks/App/iOS/DL-Info.plist
Expand Up @@ -50,5 +50,11 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>FirebaseDynamicLinksCustomDomains</key>
<array>
<string>https://google.com</string>
<string>https://google.com/one/</string>
<string>https://a.firebase.com/mypath</string>
</array>
</dict>
</plist>
42 changes: 28 additions & 14 deletions Example/DynamicLinks/FDLBuilderTestAppObjC/Info.plist
Expand Up @@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand Down Expand Up @@ -55,22 +69,22 @@
</array>
</dict>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>FirebaseDynamicLinksCustomDomains</key>
<array>
<string>https://mydomain.com</string>
<string>https://mydomain2.com</string>
<string>https://google.com</string>
<string>https://google.com</string>
<string>google</string>
<string>mydomain.com</string>
<string>https://mydomain</string>
<string>https://mydomain3.com</string>
<string>https://google.com/one</string>
<string>https://custom.com/one/two</string>
<string>https://custom1.com/one/</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
9 changes: 5 additions & 4 deletions Example/DynamicLinks/FDLBuilderTestAppObjC/ViewController.m
Expand Up @@ -155,9 +155,9 @@ - (void)_initDefaultValues {
},
// The default value of domain appcode belongs to project: app-invites-qa
@{
@"id" : @"domain",
@"label" : @"App domain (required)",
@"defaultValue" : @"testfdl.page.link",
@"id" : @"domainURIPrefix",
@"label" : @"App domainURIPrefix (required)",
@"defaultValue" : @"https://testfdl.page.link",
},
// analytics params
@{
Expand Down Expand Up @@ -289,7 +289,8 @@ - (void)_initDefaultValues {
- (void)_buildFDLLink {
NSURL *link = [NSURL URLWithString:_paramValues[@"linkString"]];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:_paramValues[@"domain"]];
[FIRDynamicLinkComponents componentsWithLink:link
domainURIPrefix:_paramValues[@"https://domain"]];

FIRDynamicLinkGoogleAnalyticsParameters *analyticsParams =
[FIRDynamicLinkGoogleAnalyticsParameters
Expand Down
19 changes: 19 additions & 0 deletions Example/DynamicLinks/FDLBuilderTestAppObjCTests/Info.plist
Expand Up @@ -18,5 +18,24 @@
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;array&gt;
&lt;string&gt;https://mydomain.com&lt;/string&gt;
&lt;string&gt;https://mydomain2.com&lt;/string&gt;
&lt;string&gt;https://google.com&lt;/string&gt;
&lt;string&gt;https://google.com&lt;/string&gt;
&lt;string&gt;go&lt;/string&gt;
&lt;string&gt;g.co&lt;/string&gt;
&lt;string&gt;https://go&lt;/string&gt;
&lt;string&gt;https://g.co&lt;/string&gt;
&lt;string&gt;https://google.com/one&lt;/string&gt;
&lt;string&gt;https://custom.com/one/two&lt;/string&gt;
&lt;string&gt;https://custom1.com/one/&lt;/string&gt;
&lt;/array&gt;
&lt;/plist&gt;
</key>
<string></string>
</dict>
</plist>
124 changes: 103 additions & 21 deletions Example/DynamicLinks/Tests/FDLURLComponentsTests.m
Expand Up @@ -21,7 +21,8 @@

#import <OCMock/OCMock.h>

static NSString *const kFDLURLDomain = @"xyz.page.link";
static NSString *const kFDLURLDomain = @"https://xyz.page.link";
static NSString *const kFDLURLCustomDomain = @"https://foo.com/path";

@interface FDLURLComponentsTests : XCTestCase
@end
Expand Down Expand Up @@ -461,14 +462,14 @@ - (void)testLinkOptionsParamsPropertiesSetProperly {

- (void)testFDLComponentsFactoryReturnsInstanceOfCorrectClass {
NSURL *link = [NSURL URLWithString:@"https://google.com"];
id returnValue = [FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, something I just realized now: it'd be good to keep a few tests around still for the old constructor to make sure we don't accidentally break it. I won't block this PR on it, but please add a few tests to make sure the old constructor isn't nil regardless of what's passed in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will add more tests for the deprecated constructor.

id returnValue = [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkComponents class]]);
}

- (void)testFDLComponentsFactoryReturnsInstanceWithAllNilProperties {
NSURL *link = [NSURL URLWithString:@"https://google.com"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];

XCTAssertNil(components.analyticsParameters);
XCTAssertNil(components.socialMetaTagParameters);
Expand All @@ -484,11 +485,27 @@ - (void)testFDLComponentsCreatesSimplestLinkCorrectly {
NSURL *link = [NSURL URLWithString:linkString];

NSString *expectedURLString =
[NSString stringWithFormat:@"https://%@/?link=%@", kFDLURLDomain, endcodedLinkString];
[NSString stringWithFormat:@"%@/?link=%@", kFDLURLDomain, endcodedLinkString];
NSURL *expectedURL = [NSURL URLWithString:expectedURLString];

FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
NSURL *actualURL = components.url;

XCTAssertEqualObjects(actualURL, expectedURL);
}

- (void)testFDLComponentsCustomDomainWithPath {
NSString *linkString = @"https://google.com";
NSString *endcodedLinkString = @"https%3A%2F%2Fgoogle%2Ecom";
NSURL *link = [NSURL URLWithString:linkString];

NSString *expectedURLString =
[NSString stringWithFormat:@"%@/?link=%@", kFDLURLCustomDomain, endcodedLinkString];
NSURL *expectedURL = [NSURL URLWithString:expectedURLString];

FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLCustomDomain];
NSURL *actualURL = components.url;

XCTAssertEqualObjects(actualURL, expectedURL);
Expand All @@ -499,7 +516,8 @@ - (void)testFDLComponentsFailsOnMalformedDomain {
NSURL *link = [NSURL URLWithString:linkString];

FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:@"this is invalid domain"];
[FIRDynamicLinkComponents componentsWithLink:link
domainURIPrefix:@"this is invalid domain URI Prefix"];

XCTAssertNil(components.url);
}
Expand Down Expand Up @@ -553,7 +571,7 @@ - (void)testFDLComponentsCreatesFullLinkCorrectly {

NSURL *link = [NSURL URLWithString:@"https://google.com"];
FIRDynamicLinkComponents *fdlComponents =
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
fdlComponents.analyticsParameters = analyticsParams;
fdlComponents.iOSParameters = iosParams;
fdlComponents.iTunesConnectParameters = itcParams;
Expand Down Expand Up @@ -642,7 +660,80 @@ - (void)testShortenURL {
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
[components
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
NSError *_Nullable error) {
XCTAssertEqualObjects(shortURL.absoluteString, shortURLString);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:0.1 handler:nil];

[keyProviderClassMock verify];
[keyProviderClassMock stopMocking];
[componentsClassMock verify];
[componentsClassMock stopMocking];
}

- (void)testDeprecatedMethodComponentsWithLinkForDomain {
NSString *shortURLString = @"https://xyz.page.link/abcd";

// Mock key provider
id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]);
[[[keyProviderClassMock expect] andReturn:@"fake-api-key"] APIKey];

id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]);
[[componentsClassMock expect]
sendHTTPRequest:OCMOCK_ANY
completion:[OCMArg checkWithBlock:^BOOL(id obj) {
void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj;
NSDictionary *JSON = @{@"shortLink" : shortURLString};
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0];
completion(JSONData, nil);
return YES;
}]];

XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:@"xyz.page.link"];
[components
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
NSError *_Nullable error) {
XCTAssertEqualObjects(shortURL.absoluteString, shortURLString);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:0.1 handler:nil];

[keyProviderClassMock verify];
[keyProviderClassMock stopMocking];
[componentsClassMock verify];
[componentsClassMock stopMocking];
}

- (void)testDeprecatedMethodComponentsWithLinkForDomainWithInvalidDomainScheme {
NSString *shortURLString = @"https://xyz.page.link/abcd";

// Mock key provider
id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]);
[[[keyProviderClassMock expect] andReturn:@"fake-api-key"] APIKey];

id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]);
[[componentsClassMock expect]
sendHTTPRequest:OCMOCK_ANY
completion:[OCMArg checkWithBlock:^BOOL(id obj) {
void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj;
NSDictionary *JSON = @{@"shortLink" : shortURLString};
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0];
completion(JSONData, nil);
return YES;
}]];

XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:@"http://xyz.page.link"];
XCTAssertNotNil(components);
[components
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
NSError *_Nullable error) {
Expand Down Expand Up @@ -679,7 +770,7 @@ - (void)testShortenURLReturnsErrorWhenAPIKeyMissing {
[self expectationWithDescription:@"completion called with error"];
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
[components
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
NSError *_Nullable error) {
Expand Down Expand Up @@ -714,20 +805,11 @@ - (void)testShortenURLReturnsErrorWhenDomainIsMalformed {
return YES;
}]];

XCTestExpectation *expectation =
[self expectationWithDescription:@"completion called with error"];
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
FIRDynamicLinkComponents *components =
[FIRDynamicLinkComponents componentsWithLink:link domain:@"this is invalid domain"];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would also be good to keep (along with the new nil test) - ensure that an invalid components with the old constructor throws an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will add more tests for the deprecated constructor.

[components
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
NSError *_Nullable error) {
XCTAssertNil(shortURL);
if (error) {
[expectation fulfill];
}
}];
[self waitForExpectationsWithTimeout:0.1 handler:nil];
[FIRDynamicLinkComponents componentsWithLink:link
domainURIPrefix:@"this is invalid domain URI Prefix"];
XCTAssertNil(components);

[keyProviderClassMock verify];
[keyProviderClassMock stopMocking];
Expand Down
2 changes: 1 addition & 1 deletion Example/DynamicLinks/Tests/FIRDynamicLinkNetworkingTests.m
Expand Up @@ -16,7 +16,7 @@

#import <XCTest/XCTest.h>

#import "OCMock.h"
#import <OCMock/OCMock.h>

#import <GoogleUtilities/GULSwizzler.h>
#import "DynamicLinks/FIRDynamicLinkNetworking+Private.h"
Expand Down
59 changes: 58 additions & 1 deletion Example/DynamicLinks/Tests/FIRDynamicLinksTest.m
Expand Up @@ -161,6 +161,9 @@ @implementation FIRDynamicLinksTest

- (void)setUp {
[super setUp];
if (!(FIRApp.defaultApp)) {
[FIRApp configure];
}
self.service = [[FIRDynamicLinks alloc] init];
self.userDefaults = [[NSUserDefaults alloc] init];
[self.userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
Expand Down Expand Up @@ -223,7 +226,6 @@ - (void)testURLScheme_MinimumParameters {
}

- (void)testFactoryMethodReturnsProperClassObject {
[FIRApp configure];
id service = [FIRDynamicLinks dynamicLinks];

XCTAssertNotNil(service, @"Factory method returned nil");
Expand Down Expand Up @@ -1015,6 +1017,61 @@ - (void)testSelfDiagnoseCompletionCalled {
[self waitForExpectationsWithTimeout:2.0 handler:nil];
}

#pragma mark - Custom domain tests
- (void)testValidCustomDomainNames {
// Entries in plist file:
// https://google.com
// https://google.com/one
// https://a.firebase.com/mypath

NSArray<NSString *> *urlStrings = @[
@"https://google.com/mylink", // Short FDL starting with 'https://google.com'
@"https://google.com/one", // Short FDL starting with 'https://google.com'
@"https://google.com?link=abcd", // Long FDL starting with 'https://google.com'
@"https://google.com/one/mylink", // Long FDL starting with 'https://google.com/one'
@"https://a.firebase.com/mypath/mylink", // Short FDL starting https://a.firebase.com/mypath
@"https://a.firebase.com/mypath?link=abcd&test=1", // Long FDL starting with
// https://a.firebase.com/mypath
];

for (NSString *urlString in urlStrings) {
NSURL *url = [NSURL URLWithString:urlString];
BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url];

XCTAssertTrue(matchesShortLinkFormat,
@"Non-DDL domain URL matched short link format with URL: %@", url);
}
}

- (void)testInvalidCustomDomainNames {
// Entries in plist file:
// https://google.com
// https://google.com/one
// https://a.firebase.com/mypath

NSArray<NSString *> *urlStrings = @[
@"google.com", // Valid domain. No scheme.
@"https://google.com", // Valid domain. No path after domainURIPrefix.
@"https://google.com/", // Valid domain. No path after domainURIPrefix.
@"https://google.com/one/", // Valid domain. No path after domainURIPrefix.
@"https://google.com/one/two/mylink", // domainURIPrefix not exact match.
@"https://google.co.in/mylink", // No matching domainURIPrefix.
@"https://firebase.com/mypath", // No matching domainURIPrefix: Invalid (sub)domain.
@"https://b.firebase.com/mypath", // No matching domainURIPrefix: Invalid subdomain.
@"https://a.firebase.com/mypathabc", // No matching domainURIPrefix: Invalid subdomain.
@"mydomain.com", // https scheme not specified for domainURIPrefix.
@"http://mydomain", // Domain not in plist. No path after domainURIPrefix.
];

for (NSString *urlString in urlStrings) {
NSURL *url = [NSURL URLWithString:urlString];
BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url];

XCTAssertFalse(matchesShortLinkFormat,
@"Non-DDL domain URL matched short link format with URL: %@", url);
}
}

#pragma mark - Private Helpers

- (void)removeAllFIRApps {
Expand Down