From e9cfa8ce576a64bc27e1bb7b2078a67fe27bf1ac Mon Sep 17 00:00:00 2001 From: Ian Keith Date: Mon, 8 Mar 2021 19:13:02 -0500 Subject: [PATCH 1/5] Fix for the Obj-C accessor only handling strings and not date objects. --- ios/Capacitor/Capacitor/CAPBridgedJSTypes.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m index 686531a3a4..cc393a2fd9 100644 --- a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m +++ b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m @@ -12,7 +12,10 @@ - (NSString * _Nullable)getString:(NSString * _Nonnull)key defaultValue:(NSStrin - (NSDate * _Nullable)getDate:(NSString * _Nonnull)key defaultValue:(NSDate * _Nullable)defaultValue { id value = [[self dictionaryRepresentation] objectForKey:key]; - if (value != nil && [value isKindOfClass:[NSString class]]) { + if (value != nil && [value isKindOfClass:[NSDate class]]) { + return value; + } + else if (value != nil && [value isKindOfClass:[NSString class]]) { return [[[self class] jsDateFormatter] dateFromString:value]; } return defaultValue; From 07dc725dd3f6a2b1c79614a92b3d5bd9952151a1 Mon Sep 17 00:00:00 2001 From: Ian Keith Date: Mon, 8 Mar 2021 19:13:27 -0500 Subject: [PATCH 2/5] Adding NSNumber accessor to Obj-C accessors. --- ios/Capacitor/Capacitor/CAPBridgedJSTypes.h | 1 + ios/Capacitor/Capacitor/CAPBridgedJSTypes.m | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h index ecf3129642..a5ac367d5c 100644 --- a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h +++ b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h @@ -10,6 +10,7 @@ - (NSString * _Nullable)getString:(NSString * _Nonnull)key defaultValue:(NSString * _Nullable)defaultValue; - (NSDate * _Nullable)getDate:(NSString * _Nonnull)key defaultValue:(NSDate * _Nullable)defaultValue; - (NSDictionary * _Nullable)getObject:(NSString * _Nonnull)key defaultValue:(NSDictionary * _Nullable)defaultValue; +- (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumber * _Nullable)defaultValue; @end @interface CAPPluginCall (BridgedJSProtocol) diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m index cc393a2fd9..47353eaa75 100644 --- a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m +++ b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m @@ -28,4 +28,12 @@ - (NSDictionary * _Nullable)getObject:(NSString * _Nonnull)key defaultValue:(NSD } return defaultValue; } + +- (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumber * _Nullable)defaultValue { + id value = [[self dictionaryRepresentation] objectForKey:key]; + if (value != nil && [value isKindOfClass:[NSNumber class]]) { + return value; + } + return defaultValue; +} @end From d45ae1c0c65a844361da2aab29f5f18f5278cf6f Mon Sep 17 00:00:00 2001 From: Ian Keith Date: Mon, 8 Mar 2021 19:14:03 -0500 Subject: [PATCH 3/5] Deprecating convenience accessors on CAPPlugin, falling through to the implementation on the call. --- ios/Capacitor/Capacitor/CAPPlugin.h | 4 ++-- ios/Capacitor/Capacitor/CAPPlugin.m | 32 ++++++----------------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/ios/Capacitor/Capacitor/CAPPlugin.h b/ios/Capacitor/Capacitor/CAPPlugin.h index d0814cb253..4f77e31f37 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.h +++ b/ios/Capacitor/Capacitor/CAPPlugin.h @@ -42,8 +42,8 @@ // need to override init() -(void)load; -(NSString* _Nonnull)getId; --(BOOL)getBool:(CAPPluginCall* _Nonnull) call field:(NSString* _Nonnull)field defaultValue:(BOOL)defaultValue; --(NSString* _Nullable)getString:(CAPPluginCall* _Nonnull)call field:(NSString* _Nonnull)field defaultValue:(NSString* _Nonnull)defaultValue; +-(BOOL)getBool:(CAPPluginCall* _Nonnull) call field:(NSString* _Nonnull)field defaultValue:(BOOL)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations."); +-(NSString* _Nullable)getString:(CAPPluginCall* _Nonnull)call field:(NSString* _Nonnull)field defaultValue:(NSString* _Nonnull)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations."); -(id _Nullable)getConfigValue:(NSString* _Nonnull)key; -(void)setCenteredPopover:(UIViewController* _Nonnull)vc; -(BOOL)supportsPopover; diff --git a/ios/Capacitor/Capacitor/CAPPlugin.m b/ios/Capacitor/Capacitor/CAPPlugin.m index 63634d982d..517ad44288 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.m +++ b/ios/Capacitor/Capacitor/CAPPlugin.m @@ -1,4 +1,5 @@ #import "CAPPlugin.h" +#import "CAPBridgedJSTypes.h" #import #import @@ -19,34 +20,13 @@ -(NSString *) getId { return self.pluginName; } --(BOOL) getBool:(CAPPluginCall *)call field:(NSString *)field defaultValue:(BOOL)defaultValue { - id idVal = [call.options objectForKey:field]; - - if(![idVal isKindOfClass:[NSNumber class]]) { - return defaultValue; - } - - NSNumber *value = (NSNumber *)idVal; - if(value == nil) { - return defaultValue; - } - if(value.integerValue == 0) { - return FALSE; - } - return TRUE; +- (BOOL)getBool:(CAPPluginCall *)call field:(NSString *)field defaultValue:(BOOL)defaultValue { + NSNumber* value = [call getNumber:field defaultValue:[NSNumber numberWithBool:defaultValue]]; + return [value boolValue]; } --(NSString *) getString:(CAPPluginCall *)call field:(NSString *)field defaultValue:(NSString *)defaultValue -{ - id idVal = [call.options objectForKey:field]; - if(![idVal isKindOfClass:[NSString class]]) { - return defaultValue; - } - NSString *value = (NSString *)idVal; - if(value == nil) { - return defaultValue; - } - return value; +- (NSString *) getString:(CAPPluginCall *)call field:(NSString *)field defaultValue:(NSString *)defaultValue { + return [call getString:field defaultValue:defaultValue]; } -(id)getConfigValue:(NSString *)key { From ef12a91aa528c0e319e7eaf2f88de917f3f58a76 Mon Sep 17 00:00:00 2001 From: Ian Keith Date: Mon, 8 Mar 2021 19:14:28 -0500 Subject: [PATCH 4/5] Adding unit tests for the Obj-C convenience accessors. --- .../Capacitor.xcodeproj/project.pbxproj | 4 + .../CapacitorTests/PluginCallAccessorTests.m | 91 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m diff --git a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj b/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj index d5297cc11b..b6f67624a0 100644 --- a/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj +++ b/ios/Capacitor/Capacitor.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 623D691D254C7462002D01D1 /* CAPInstanceConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 623D691E254C7462002D01D1 /* CAPInstanceConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */; }; 625AF1ED258963C700869675 /* WebViewAssetHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */; }; + 6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */; }; 62959B162524DA7800A3D7F1 /* CAPPluginCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */; settings = {ATTRIBUTES = (Public, ); }; }; 62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE32524DA7700A3D7F1 /* JSExport.swift */; }; 62959B192524DA7800A3D7F1 /* CAPBridgedPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -153,6 +154,7 @@ 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CAPInstanceConfiguration.h; sourceTree = ""; }; 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAPInstanceConfiguration.m; sourceTree = ""; }; 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewAssetHandler.swift; sourceTree = ""; }; + 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PluginCallAccessorTests.m; sourceTree = ""; }; 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPPluginCall.h; sourceTree = ""; }; 62959AE32524DA7700A3D7F1 /* JSExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSExport.swift; sourceTree = ""; }; 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPBridgedPlugin.h; sourceTree = ""; }; @@ -275,6 +277,7 @@ 62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */, 621ECCC7254204BE00D3D615 /* JSONSerializationWrapper.h */, 621ECCC6254204BE00D3D615 /* JSONSerializationWrapper.m */, + 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */, 621ECCCD254204C400D3D615 /* CapacitorTests-Bridging-Header.h */, 62959BBD2526510200A3D7F1 /* Info.plist */, ); @@ -603,6 +606,7 @@ 62A91C3425535F5700861508 /* ConfigurationTests.swift in Sources */, 62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */, 621ECCC3254204B700D3D615 /* BridgedTypesTests.swift in Sources */, + 6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m b/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m new file mode 100644 index 0000000000..d805baa2e2 --- /dev/null +++ b/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m @@ -0,0 +1,91 @@ +#import +#import +#import +// forward declaration of internal capacitor classes that are exposed in the swift header via the @testable import. +@interface CAPWebViewAssetHandler: NSObject +@end +@interface CapacitorBridge: NSObject +@end +@interface CAPWebViewDelegationHandler: NSObject +@end +// import that will fail without the declarations +#import "CapacitorTests-Swift.h" + +// interface for this class +@interface PluginCallAccessorTests : XCTestCase +@property (strong, nonatomic) CAPPluginCall* call; +@end + +@implementation PluginCallAccessorTests + +- (void)setUp { + [super setUp]; + NSDate* date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:632854800]; + NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init]; + NSDictionary* options = @{@"testString":@"foo", + @"testDict": @{@"testSubkey":@"sub value"}, + @"testFloat": @3.14159, + @"testDateObject": date, + @"testDateString": [formatter stringFromDate:date], + @"testBool": @TRUE}; + [self setCall:[[CAPPluginCall alloc] initWithCallbackId:@"test" options:options success:NULL error:NULL]]; +} + +- (void)testStringAccessor { + NSString* value = [[self call] getString:@"testString" defaultValue:NULL]; + XCTAssertEqual(value, @"foo"); + + value = [[self call] getString:@"badString" defaultValue:NULL]; + XCTAssertNil(value); + + value = [[self call] getString:@"badString" defaultValue:@"default"]; + XCTAssertEqual(value, @"default"); +} + +- (void)testDateObjectAccessor { + NSDate* value = [[self call] getDate:@"testDateObject" defaultValue:NULL]; + XCTAssertEqual([value timeIntervalSinceReferenceDate], 632854800); + + value = [[self call] getDate:@"badString" defaultValue:NULL]; + XCTAssertNil(value); + + NSDate *defaultDate = [NSDate date]; + value = [[self call] getDate:@"badString" defaultValue:defaultDate]; + XCTAssertEqual(value, defaultDate); +} + +- (void)testDateStringAccessor { + NSDate* objectValue = [[self call] getDate:@"testDateObject" defaultValue:NULL]; + NSDate* stringValue = [[self call] getDate:@"testDateString" defaultValue:NULL]; + XCTAssertNotNil(objectValue); + XCTAssertNotNil(stringValue); + XCTAssertEqual(objectValue, stringValue); +} + +- (void)testObjectAccessor { + NSDictionary* value = [[self call] getObject:@"testDict" defaultValue:NULL]; + XCTAssertEqual([value objectForKey:@"testSubkey"], @"sub value"); + + value = [[self call] getObject:@"badString" defaultValue:NULL]; + XCTAssertNil(value); + + value = [[self call] getObject:@"badString" defaultValue:@{@"defaultKey":@"default"}]; + XCTAssertEqual([value objectForKey:@"defaultKey"], @"default"); +} + +- (void)testNumberAccessor { + NSNumber* value = [[self call] getNumber:@"testFloat" defaultValue:NULL]; + XCTAssertNotNil(value); + XCTAssertTrue([value isEqualToNumber:@3.14159]); + + value = [[self call] getNumber:@"badString" defaultValue:NULL]; + XCTAssertNil(value); + + value = [[self call] getNumber:@"badString" defaultValue:@100]; + XCTAssertEqual([value intValue], 100); + + value = [[self call] getNumber:@"testBool" defaultValue:NULL]; + XCTAssertNotNil(value); + XCTAssertEqual([value boolValue], TRUE); +} +@end From 823ff441304d67e6e34d356b602c0b9c66b88d21 Mon Sep 17 00:00:00 2001 From: Ian Keith Date: Tue, 9 Mar 2021 13:01:49 -0500 Subject: [PATCH 5/5] Adding `getBool` accessor for Obj-C. --- ios/Capacitor/Capacitor/CAPBridgedJSTypes.h | 1 + ios/Capacitor/Capacitor/CAPBridgedJSTypes.m | 4 ++++ .../CapacitorTests/PluginCallAccessorTests.m | 19 +++++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h index a5ac367d5c..516c8648b8 100644 --- a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h +++ b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.h @@ -11,6 +11,7 @@ - (NSDate * _Nullable)getDate:(NSString * _Nonnull)key defaultValue:(NSDate * _Nullable)defaultValue; - (NSDictionary * _Nullable)getObject:(NSString * _Nonnull)key defaultValue:(NSDictionary * _Nullable)defaultValue; - (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumber * _Nullable)defaultValue; +- (BOOL)getBool:(NSString * _Nonnull)key defaultValue:(BOOL)defaultValue; @end @interface CAPPluginCall (BridgedJSProtocol) diff --git a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m index 47353eaa75..fb6da4586f 100644 --- a/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m +++ b/ios/Capacitor/Capacitor/CAPBridgedJSTypes.m @@ -36,4 +36,8 @@ - (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumbe } return defaultValue; } + +- (BOOL)getBool:(NSString * _Nonnull)key defaultValue:(BOOL)defaultValue { + return [[self getNumber:key defaultValue:[NSNumber numberWithBool:defaultValue]] boolValue]; +} @end diff --git a/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m b/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m index d805baa2e2..0f8269c153 100644 --- a/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m +++ b/ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m @@ -27,7 +27,8 @@ - (void)setUp { @"testFloat": @3.14159, @"testDateObject": date, @"testDateString": [formatter stringFromDate:date], - @"testBool": @TRUE}; + @"testBoolTrue": @TRUE, + @"testBoolFalse": @FALSE}; [self setCall:[[CAPPluginCall alloc] initWithCallbackId:@"test" options:options success:NULL error:NULL]]; } @@ -84,8 +85,22 @@ - (void)testNumberAccessor { value = [[self call] getNumber:@"badString" defaultValue:@100]; XCTAssertEqual([value intValue], 100); - value = [[self call] getNumber:@"testBool" defaultValue:NULL]; + value = [[self call] getNumber:@"testBoolTrue" defaultValue:NULL]; XCTAssertNotNil(value); XCTAssertEqual([value boolValue], TRUE); } + +- (void)testBoolAccessor { + BOOL value = [[self call] getBool:@"testBoolTrue" defaultValue:false]; + XCTAssertTrue(value); + + value = [[self call] getBool:@"testBoolFalse" defaultValue:true]; + XCTAssertFalse(value); + + value = [[self call] getBool:@"badString" defaultValue:true]; + XCTAssertTrue(value); + + value = [[self call] getBool:@"badString" defaultValue:false]; + XCTAssertFalse(value); +} @end