diff options
-rw-r--r-- | SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 16 | ||||
-rw-r--r-- | SmartDeviceLink/SDLMenuManager.m | 36 | ||||
-rw-r--r-- | SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m | 47 | ||||
-rw-r--r-- | SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m | 123 | ||||
-rw-r--r-- | SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m | 123 | ||||
-rw-r--r-- | SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m | 113 |
6 files changed, 334 insertions, 124 deletions
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 19fccee2f..2ebce40e7 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -974,6 +974,8 @@ 5DA49CE61F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DA49CE41F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m */; }; 5DA8A0E91E955F710039C50D /* SDLStreamingMediaManagerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */; }; 5DA8A0EA1E955FE00039C50D /* SDLLogModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBF06301E64A9C600A5CF03 /* SDLLogModel.m */; }; + 5DAB5F512098994C00A020C8 /* SDLMenuCellSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */; }; + 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */; }; 5DAD5F7F204DEDEB0025624C /* SDLScreenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5DAD5F80204DEDEB0025624C /* SDLScreenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD5F7E204DEDEB0025624C /* SDLScreenManager.m */; }; 5DAD5F8520507E1F0025624C /* SDLScreenManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD5F8420507E1F0025624C /* SDLScreenManagerSpec.m */; }; @@ -1060,7 +1062,7 @@ 5DF40B22208E761A00DD6FDA /* SDLVoiceCommandManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DF40B20208E761A00DD6FDA /* SDLVoiceCommandManager.h */; }; 5DF40B23208E761A00DD6FDA /* SDLVoiceCommandManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B21208E761A00DD6FDA /* SDLVoiceCommandManager.m */; }; 5DF40B26208FA7DE00DD6FDA /* SDLMenuManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */; }; - 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandSpec.m */; }; + 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */; }; 5DFFB9151BD7C89700DB3F04 /* SDLConnectionManagerType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */; }; 880E8C2920697FEE00CF86C2 /* SDLSystemCapabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 880E8C2720697FEE00CF86C2 /* SDLSystemCapabilityManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 880E8C2A20697FEE00CF86C2 /* SDLSystemCapabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 880E8C2820697FEE00CF86C2 /* SDLSystemCapabilityManager.m */; }; @@ -2243,6 +2245,8 @@ 5DA3F36F1BC4489A0026F2D0 /* SDLManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLManager.m; sourceTree = "<group>"; }; 5DA49CE31F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLControlFramePayloadRPCStartService.h; sourceTree = "<group>"; }; 5DA49CE41F1EA83300E65FC5 /* SDLControlFramePayloadRPCStartService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLControlFramePayloadRPCStartService.m; sourceTree = "<group>"; }; + 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLMenuCellSpec.m; path = DevAPISpecs/SDLMenuCellSpec.m; sourceTree = "<group>"; }; + 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLVoiceCommandSpec.m; path = DevAPISpecs/SDLVoiceCommandSpec.m; sourceTree = "<group>"; }; 5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLScreenManager.h; sourceTree = "<group>"; }; 5DAD5F7E204DEDEB0025624C /* SDLScreenManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLScreenManager.m; sourceTree = "<group>"; }; 5DAD5F8420507E1F0025624C /* SDLScreenManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLScreenManagerSpec.m; sourceTree = "<group>"; }; @@ -2339,7 +2343,7 @@ 5DF40B20208E761A00DD6FDA /* SDLVoiceCommandManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLVoiceCommandManager.h; sourceTree = "<group>"; }; 5DF40B21208E761A00DD6FDA /* SDLVoiceCommandManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVoiceCommandManager.m; sourceTree = "<group>"; }; 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLMenuManagerSpec.m; path = DevAPISpecs/SDLMenuManagerSpec.m; sourceTree = "<group>"; }; - 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLVoiceCommandSpec.m; path = DevAPISpecs/SDLVoiceCommandSpec.m; sourceTree = "<group>"; }; + 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLVoiceCommandManagerSpec.m; path = DevAPISpecs/SDLVoiceCommandManagerSpec.m; sourceTree = "<group>"; }; 5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLConnectionManagerType.h; sourceTree = "<group>"; }; 880E8C2720697FEE00CF86C2 /* SDLSystemCapabilityManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLSystemCapabilityManager.h; sourceTree = "<group>"; }; 880E8C2820697FEE00CF86C2 /* SDLSystemCapabilityManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLSystemCapabilityManager.m; sourceTree = "<group>"; }; @@ -4730,7 +4734,9 @@ isa = PBXGroup; children = ( 5DF40B25208FA7DE00DD6FDA /* SDLMenuManagerSpec.m */, - 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandSpec.m */, + 5DF40B27208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m */, + 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */, + 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */, ); name = Menu; sourceTree = "<group>"; @@ -5945,6 +5951,7 @@ 5DBEFA581F436132009EE295 /* SDLFakeSecurityManager.m in Sources */, 162E82D91A9BDE8A00906325 /* SDLDisplayTypeSpec.m in Sources */, 162E83871A9BDE8B00906325 /* SDLPermissionItemSpec.m in Sources */, + 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */, 162E82E31A9BDE8B00906325 /* SDLIgnitionStatusSpec.m in Sources */, 162E83511A9BDE8B00906325 /* SDLDeleteInteractionChoiceSetResponseSpec.m in Sources */, DA9F7EB41DCC086400ACAE48 /* SDLDateTimeSpec.m in Sources */, @@ -5969,6 +5976,7 @@ 162E83681A9BDE8B00906325 /* SDLSpeakResponseSpec.m in Sources */, 162E83661A9BDE8B00906325 /* SDLShowResponseSpec.m in Sources */, 5D9F50831BEA5C6100FEF399 /* SDLFileManagerSpec.m in Sources */, + 5DAB5F512098994C00A020C8 /* SDLMenuCellSpec.m in Sources */, 1EE8C4481F38430900FDC2CF /* SDLRadioControlCapabilitiesSpec.m in Sources */, 162E83221A9BDE8B00906325 /* SDLAddCommandSpec.m in Sources */, 162E83121A9BDE8B00906325 /* SDLOnButtonPressSpec.m in Sources */, @@ -6232,7 +6240,7 @@ 162E82CF1A9BDE8A00906325 /* SDLBitsPerSampleSpec.m in Sources */, 162E831E1A9BDE8B00906325 /* SDLOnTBTClientStateSpec.m in Sources */, 162E83351A9BDE8B00906325 /* SDLReadDIDSpec.m in Sources */, - 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandSpec.m in Sources */, + 5DF40B28208FDA9700DD6FDA /* SDLVoiceCommandManagerSpec.m in Sources */, 162E836F1A9BDE8B00906325 /* SDLUnsubscribeVehicleDataResponseSpec.m in Sources */, 162E82DB1A9BDE8B00906325 /* SDLECallConfirmationStatusSpec.m in Sources */, 162E82D81A9BDE8A00906325 /* SDLDimensionSpec.m in Sources */, diff --git a/SmartDeviceLink/SDLMenuManager.m b/SmartDeviceLink/SDLMenuManager.m index de75ce96d..39b6bc91c 100644 --- a/SmartDeviceLink/SDLMenuManager.m +++ b/SmartDeviceLink/SDLMenuManager.m @@ -361,17 +361,30 @@ UInt32 const MenuCellIdMin = 1; return submenu; } +#pragma mark - Calling handlers + +- (BOOL)sdl_callHandlerForCells:(NSArray<SDLMenuCell *> *)cells command:(SDLOnCommand *)onCommand { + for (SDLMenuCell *cell in cells) { + if (cell.cellId == onCommand.cmdID.unsignedIntegerValue) { + cell.handler(onCommand.triggerSource); + return YES; + } + + if (cell.subCells.count > 0) { + BOOL succeeded = [self sdl_callHandlerForCells:cell.subCells command:onCommand]; + if (succeeded) { return YES; } + } + } + + return NO; +} + #pragma mark - Observers - (void)sdl_commandNotification:(SDLRPCNotificationNotification *)notification { SDLOnCommand *onCommand = (SDLOnCommand *)notification.notification; - for (SDLMenuCell *cell in self.menuCells) { - if (onCommand.cmdID.unsignedIntegerValue != cell.cellId) { continue; } - - cell.handler(onCommand.triggerSource); - break; - } + [self sdl_callHandlerForCells:self.menuCells command:onCommand]; } - (void)sdl_registerResponse:(SDLRPCResponseNotification *)notification { @@ -390,11 +403,12 @@ UInt32 const MenuCellIdMin = 1; self.currentHMILevel = hmiStatus.hmiLevel; // Auto-send an updated menu if we were in NONE and now we are not, and we need an update - if ([oldHMILevel isEqualToString:SDLHMILevelNone] && ![self.currentHMILevel isEqualToString:SDLHMILevelNone]) { + if ([oldHMILevel isEqualToString:SDLHMILevelNone] && ![self.currentHMILevel isEqualToString:SDLHMILevelNone] && + ![self.currentSystemContext isEqualToEnum:SDLSystemContextMenu]) { if (self.waitingOnHMIUpdate) { - [self setMenuCells:_menuCells]; - } else { - [self sdl_updateWithCompletionHandler:nil]; + [self setMenuCells:self.waitingUpdateMenuCells]; + self.waitingUpdateMenuCells = @[]; + return; } } @@ -402,7 +416,7 @@ UInt32 const MenuCellIdMin = 1; SDLSystemContext oldSystemContext = self.currentSystemContext; self.currentSystemContext = hmiStatus.systemContext; - if ([oldSystemContext isEqualToEnum:SDLSystemContextMenu] && ![self.currentSystemContext isEqualToEnum:SDLSystemContextMenu]) { + if ([oldSystemContext isEqualToEnum:SDLSystemContextMenu] && ![self.currentSystemContext isEqualToEnum:SDLSystemContextMenu] && ![self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) { if (self.waitingOnHMIUpdate) { [self setMenuCells:self.waitingUpdateMenuCells]; self.waitingUpdateMenuCells = @[]; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m new file mode 100644 index 000000000..b6b52f0a0 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuCellSpec.m @@ -0,0 +1,47 @@ +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> + +#import "SDLArtwork.h" +#import "SDLMenuCell.h" + +QuickSpecBegin(SDLMenuCellSpec) + +describe(@"a menu cell", ^{ + __block SDLMenuCell *testCell = nil; + + describe(@"initializing", ^{ + __block NSString *someTitle = nil; + __block SDLArtwork *someArtwork = nil; + __block NSArray<NSString *> *someVoiceCommands = nil; + __block NSArray<SDLMenuCell *> *someSubcells = nil; + + beforeEach(^{ + someTitle = @"Some Title"; + someArtwork = [[SDLArtwork alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:@"data" options:kNilOptions] name:@"Some artwork" fileExtension:@"png" persistent:NO]; + someVoiceCommands = @[@"some command"]; + + SDLMenuCell *subcell = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + someSubcells = @[subcell]; + }); + + it(@"should initialize properly as a menu item", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle icon:someArtwork voiceCommands:someVoiceCommands handler:^(SDLTriggerSource _Nonnull triggerSource) {}]; + + expect(testCell.title).to(equal(someTitle)); + expect(testCell.icon).to(equal(someArtwork)); + expect(testCell.voiceCommands).to(equal(someVoiceCommands)); + expect(testCell.subCells).to(beNil()); + }); + + it(@"should initialize properly as a submenu item", ^{ + testCell = [[SDLMenuCell alloc] initWithTitle:someTitle subCells:someSubcells]; + + expect(testCell.title).to(equal(someTitle)); + expect(testCell.icon).to(beNil()); + expect(testCell.voiceCommands).to(beNil()); + expect(testCell.subCells).to(equal(someSubcells)); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m index f47748e0b..68678e230 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLMenuManagerSpec.m @@ -13,6 +13,10 @@ #import "SDLImageFieldName.h" #import "SDLMenuCell.h" #import "SDLMenuManager.h" +#import "SDLOnCommand.h" +#import "SDLOnHMIStatus.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLSystemContext.h" #import "TestConnectionManager.h" @interface SDLMenuCell() @@ -28,11 +32,13 @@ @property (weak, nonatomic) SDLFileManager *fileManager; @property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; +@property (copy, nonatomic, nullable) SDLSystemContext currentSystemContext; @property (strong, nonatomic, nullable) SDLDisplayCapabilities *displayCapabilities; @property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate; @property (assign, nonatomic) BOOL hasQueuedUpdate; @property (assign, nonatomic) BOOL waitingOnHMIUpdate; +@property (copy, nonatomic) NSArray<SDLMenuCell *> *waitingUpdateMenuCells; @property (assign, nonatomic) UInt32 lastMenuId; @property (copy, nonatomic) NSArray<SDLMenuCell *> *oldMenuCells; @@ -75,31 +81,72 @@ describe(@"menu manager", ^{ context(@"when in HMI NONE", ^{ beforeEach(^{ testManager.currentHMILevel = SDLHMILevelNone; + testManager.menuCells = @[textOnlyCell]; }); it(@"should not update", ^{ - testManager.menuCells = @[textOnlyCell]; + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + + describe(@"when entering the foreground", ^{ + beforeEach(^{ + SDLOnHMIStatus *onHMIStatus = [[SDLOnHMIStatus alloc] init]; + onHMIStatus.hmiLevel = SDLHMILevelFull; + onHMIStatus.systemContext = SDLSystemContextMain; + + SDLRPCNotificationNotification *testSystemContextNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:onHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:testSystemContextNotification]; + }); - expect(testManager.inProgressUpdate).to(beNil()); + it(@"should update", ^{ + expect(mockConnectionManager.receivedRequests).toNot(beEmpty()); + }); }); }); context(@"when no HMI level has been received", ^{ beforeEach(^{ testManager.currentHMILevel = nil; + testManager.menuCells = @[textOnlyCell]; }); it(@"should not update", ^{ + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + }); + + context(@"when in the menu", ^{ + beforeEach(^{ + testManager.currentHMILevel = SDLHMILevelFull; + testManager.currentSystemContext = SDLSystemContextMenu; testManager.menuCells = @[textOnlyCell]; + }); - expect(testManager.inProgressUpdate).to(beNil()); + it(@"should not update", ^{ + expect(mockConnectionManager.receivedRequests).to(beEmpty()); + }); + + describe(@"when exiting the menu", ^{ + beforeEach(^{ + SDLOnHMIStatus *onHMIStatus = [[SDLOnHMIStatus alloc] init]; + onHMIStatus.hmiLevel = SDLHMILevelFull; + onHMIStatus.systemContext = SDLSystemContextMain; + + SDLRPCNotificationNotification *testSystemContextNotification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:nil rpcNotification:onHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:testSystemContextNotification]; + }); + + it(@"should update", ^{ + expect(mockConnectionManager.receivedRequests).toNot(beEmpty()); + }); }); }); }); - describe(@"updating menu cell", ^{ + describe(@"updating menu cells", ^{ beforeEach(^{ testManager.currentHMILevel = SDLHMILevelFull; + testManager.currentSystemContext = SDLSystemContextMain; testManager.displayCapabilities = [[SDLDisplayCapabilities alloc] init]; SDLImageField *commandIconField = [[SDLImageField alloc] init]; @@ -194,6 +241,74 @@ describe(@"menu manager", ^{ }); }); }); + + describe(@"running menu cell handlers", ^{ + __block SDLMenuCell *cellWithHandler = nil; + __block BOOL cellCalled = NO; + __block SDLTriggerSource testTriggerSource = nil; + + beforeEach(^{ + testManager.currentHMILevel = SDLHMILevelFull; + testManager.currentSystemContext = SDLSystemContextMain; + + testManager.displayCapabilities = [[SDLDisplayCapabilities alloc] init]; + SDLImageField *commandIconField = [[SDLImageField alloc] init]; + commandIconField.name = SDLImageFieldNameCommandIcon; + testManager.displayCapabilities.imageFields = @[commandIconField]; + testManager.displayCapabilities.graphicSupported = @YES; + + cellCalled = NO; + testTriggerSource = nil; + }); + + context(@"on a main menu cell", ^{ + beforeEach(^{ + cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + cellCalled = YES; + testTriggerSource = triggerSource; + }]; + + testManager.menuCells = @[cellWithHandler]; + }); + + it(@"should call the cell handler", ^{ + SDLOnCommand *onCommand = [[SDLOnCommand alloc] init]; + onCommand.cmdID = @1; + onCommand.triggerSource = SDLTriggerSourceMenu; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveCommandNotification object:nil rpcNotification:onCommand]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + expect(cellCalled).to(beTrue()); + expect(testTriggerSource).to(equal(SDLTriggerSourceMenu)); + }); + }); + + context(@"on a submenu menu cell", ^{ + beforeEach(^{ + cellWithHandler = [[SDLMenuCell alloc] initWithTitle:@"Hello" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) { + cellCalled = YES; + testTriggerSource = triggerSource; + }]; + + SDLMenuCell *submenuCell = [[SDLMenuCell alloc] initWithTitle:@"Submenu" subCells:@[cellWithHandler]]; + + testManager.menuCells = @[submenuCell]; + }); + + it(@"should call the cell handler", ^{ + SDLOnCommand *onCommand = [[SDLOnCommand alloc] init]; + onCommand.cmdID = @2; + onCommand.triggerSource = SDLTriggerSourceMenu; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveCommandNotification object:nil rpcNotification:onCommand]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + expect(cellCalled).to(beTrue()); + expect(testTriggerSource).to(equal(SDLTriggerSourceMenu)); + }); + }); + }); }); QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m new file mode 100644 index 000000000..d9cda0f5d --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandManagerSpec.m @@ -0,0 +1,123 @@ +#import <Quick/Quick.h> +#import <Nimble/Nimble.h> +#import <OCMock/OCMock.h> + +#import "SDLAddCommand.h" +#import "SDLDeleteCommand.h" +#import "SDLFileManager.h" +#import "SDLHMILevel.h" +#import "SDLVoiceCommand.h" +#import "SDLVoiceCommandManager.h" +#import "TestConnectionManager.h" + +@interface SDLVoiceCommand() + +@property (assign, nonatomic) UInt32 commandId; + +@end + +@interface SDLVoiceCommandManager() + +@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager; + +@property (assign, nonatomic) BOOL waitingOnHMIUpdate; +@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; + +@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate; +@property (assign, nonatomic) BOOL hasQueuedUpdate; + +@property (assign, nonatomic) UInt32 lastVoiceCommandId; +@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *oldVoiceCommands; + +@end + +UInt32 const VoiceCommandIdMin = 1900000000; + +QuickSpecBegin(SDLVoiceCommandManagerSpec) + +describe(@"voice command manager", ^{ + __block SDLVoiceCommandManager *testManager = nil; + __block TestConnectionManager *mockConnectionManager = nil; + + __block SDLVoiceCommand *testVoiceCommand = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 1"] handler:^{}]; + __block SDLVoiceCommand *testVoiceCommand2 = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 2"] handler:^{}]; + + beforeEach(^{ + mockConnectionManager = [[TestConnectionManager alloc] init]; + testManager = [[SDLVoiceCommandManager alloc] initWithConnectionManager:mockConnectionManager]; + }); + + it(@"should instantiate correctly", ^{ + expect(testManager.voiceCommands).to(beEmpty()); + expect(testManager.connectionManager).to(equal(mockConnectionManager)); + expect(testManager.currentHMILevel).to(beNil()); + expect(testManager.inProgressUpdate).to(beNil()); + expect(testManager.hasQueuedUpdate).to(beFalse()); + expect(testManager.waitingOnHMIUpdate).to(beFalse()); + expect(testManager.lastVoiceCommandId).to(equal(VoiceCommandIdMin)); + expect(testManager.oldVoiceCommands).to(beEmpty()); + }); + + describe(@"updating voice commands before HMI is ready", ^{ + context(@"when in HMI NONE", ^{ + beforeEach(^{ + testManager.currentHMILevel = SDLHMILevelNone; + }); + + it(@"should not update", ^{ + testManager.voiceCommands = @[testVoiceCommand]; + expect(testManager.inProgressUpdate).to(beNil()); + }); + }); + + context(@"when no HMI level has been received", ^{ + beforeEach(^{ + testManager.currentHMILevel = nil; + }); + + it(@"should not update", ^{ + testManager.voiceCommands = @[testVoiceCommand]; + expect(testManager.inProgressUpdate).to(beNil()); + }); + }); + }); + + describe(@"updating voice commands", ^{ + beforeEach(^{ + testManager.currentHMILevel = SDLHMILevelFull; + }); + + it(@"should properly update a command", ^{ + testManager.voiceCommands = @[testVoiceCommand]; + + NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]]; + NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate]; + expect(deletes).to(beEmpty()); + + NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]]; + NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate]; + expect(add).toNot(beEmpty()); + }); + + context(@"when a menu already exists", ^{ + beforeEach(^{ + testManager.voiceCommands = @[testVoiceCommand]; + }); + + it(@"should send deletes first", ^{ + testManager.voiceCommands = @[testVoiceCommand2]; + + NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]]; + NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate]; + + NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]]; + NSArray *adds = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate]; + + expect(deletes).to(haveCount(1)); + expect(adds).to(haveCount(2)); + }); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m index 7b7c77799..8e8a2e7c3 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLVoiceCommandSpec.m @@ -1,121 +1,24 @@ #import <Quick/Quick.h> #import <Nimble/Nimble.h> -#import <OCMock/OCMock.h> -#import "SDLAddCommand.h" -#import "SDLDeleteCommand.h" -#import "SDLFileManager.h" -#import "SDLHMILevel.h" #import "SDLVoiceCommand.h" -#import "SDLVoiceCommandManager.h" -#import "TestConnectionManager.h" - -@interface SDLVoiceCommand() - -@property (assign, nonatomic) UInt32 commandId; - -@end - -@interface SDLVoiceCommandManager() - -@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager; - -@property (assign, nonatomic) BOOL waitingOnHMIUpdate; -@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; - -@property (strong, nonatomic, nullable) NSArray<SDLRPCRequest *> *inProgressUpdate; -@property (assign, nonatomic) BOOL hasQueuedUpdate; - -@property (assign, nonatomic) UInt32 lastVoiceCommandId; -@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *oldVoiceCommands; - -@end - -UInt32 const VoiceCommandIdMin = 1900000000; QuickSpecBegin(SDLVoiceCommandSpec) -describe(@"voice command manager", ^{ - __block SDLVoiceCommandManager *testManager = nil; - __block TestConnectionManager *mockConnectionManager = nil; - - __block SDLVoiceCommand *testVoiceCommand = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 1"] handler:^{}]; - __block SDLVoiceCommand *testVoiceCommand2 = [[SDLVoiceCommand alloc] initWithVoiceCommands:@[@"Test 2"] handler:^{}]; - - beforeEach(^{ - mockConnectionManager = [[TestConnectionManager alloc] init]; - testManager = [[SDLVoiceCommandManager alloc] initWithConnectionManager:mockConnectionManager]; - }); - - it(@"should instantiate correctly", ^{ - expect(testManager.voiceCommands).to(beEmpty()); - expect(testManager.connectionManager).to(equal(mockConnectionManager)); - expect(testManager.currentHMILevel).to(beNil()); - expect(testManager.inProgressUpdate).to(beNil()); - expect(testManager.hasQueuedUpdate).to(beFalse()); - expect(testManager.waitingOnHMIUpdate).to(beFalse()); - expect(testManager.lastVoiceCommandId).to(equal(VoiceCommandIdMin)); - expect(testManager.oldVoiceCommands).to(beEmpty()); - }); - - describe(@"updating voice commands before HMI is ready", ^{ - context(@"when in HMI NONE", ^{ - beforeEach(^{ - testManager.currentHMILevel = SDLHMILevelNone; - }); - - it(@"should not update", ^{ - testManager.voiceCommands = @[testVoiceCommand]; - expect(testManager.inProgressUpdate).to(beNil()); - }); - }); +describe(@"a voice command", ^{ + __block SDLVoiceCommand *testCommand = nil; - context(@"when no HMI level has been received", ^{ - beforeEach(^{ - testManager.currentHMILevel = nil; - }); - - it(@"should not update", ^{ - testManager.voiceCommands = @[testVoiceCommand]; - expect(testManager.inProgressUpdate).to(beNil()); - }); - }); - }); + describe(@"initializing", ^{ + __block NSArray<NSString *> *someVoiceCommands = nil; - describe(@"updating voice commands", ^{ beforeEach(^{ - testManager.currentHMILevel = SDLHMILevelFull; + someVoiceCommands = @[@"some command"]; }); - it(@"should properly update a command", ^{ - testManager.voiceCommands = @[testVoiceCommand]; - - NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]]; - NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate]; - expect(deletes).to(beEmpty()); - - NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]]; - NSArray *add = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate]; - expect(add).toNot(beEmpty()); - }); - - context(@"when a menu already exists", ^{ - beforeEach(^{ - testManager.voiceCommands = @[testVoiceCommand]; - }); - - it(@"should send deletes first", ^{ - testManager.voiceCommands = @[testVoiceCommand2]; - - NSPredicate *deleteCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLDeleteCommand class]]; - NSArray *deletes = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:deleteCommandPredicate]; - - NSPredicate *addCommandPredicate = [NSPredicate predicateWithFormat:@"self isMemberOfClass: %@", [SDLAddCommand class]]; - NSArray *adds = [[mockConnectionManager.receivedRequests copy] filteredArrayUsingPredicate:addCommandPredicate]; + it(@"should initialize properly", ^{ + testCommand = [[SDLVoiceCommand alloc] initWithVoiceCommands:someVoiceCommands handler:^{}]; - expect(deletes).to(haveCount(1)); - expect(adds).to(haveCount(2)); - }); + expect(testCommand.voiceCommands).to(equal(someVoiceCommands)); }); }); }); |